@@ -2,6 +2,7 @@ use adw::prelude::*;
22use adw:: subclass:: prelude:: * ;
33use gtk:: gio:: File ;
44use gtk:: { gio, glib} ;
5+ use tracing:: error;
56
67use crate :: distrobox:: { self , CreateArgName , CreateArgs , Error } ;
78use crate :: root_store:: RootStore ;
@@ -15,7 +16,7 @@ use gtk::glib::{derived_properties, Properties};
1516
1617pub enum FileRowSelection {
1718 File ,
18- Folder
19+ Folder ,
1920}
2021mod imp {
2122 use super :: * ;
@@ -41,7 +42,6 @@ mod imp {
4142 pub init_row : adw:: SwitchRow ,
4243 pub volume_rows : Rc < RefCell < Vec < adw:: EntryRow > > > ,
4344 pub scrolled_window : gtk:: ScrolledWindow ,
44- pub current_create_args : RefCell < CreateArgs > ,
4545 }
4646
4747 #[ derived_properties]
@@ -50,7 +50,6 @@ mod imp {
5050 self . obj ( ) . set_title ( "Create a Distrobox" ) ;
5151 self . obj ( ) . set_content_width ( 480 ) ;
5252
53-
5453 let toolbar_view = adw:: ToolbarView :: new ( ) ;
5554 let header = adw:: HeaderBar :: new ( ) ;
5655
@@ -99,24 +98,29 @@ mod imp {
9998 self . image_row . set_use_subtitle ( true ) ;
10099
101100 let obj = self . obj ( ) . clone ( ) ;
102- let home_row = self . obj ( ) . build_file_row ( "Select Home Directory" , FileRowSelection :: Folder , move |path| {
103- obj. set_home_folder ( Some ( path. display ( ) . to_string ( ) ) ) ;
104- } ) ;
101+ let home_row = self . obj ( ) . build_file_row (
102+ "Select Home Directory" ,
103+ FileRowSelection :: Folder ,
104+ move |path| {
105+ obj. set_home_folder ( Some ( path. display ( ) . to_string ( ) ) ) ;
106+ } ,
107+ ) ;
105108 self . home_row_expander . set_title ( "Custom Home Directory" ) ;
106109 self . home_row_expander . set_show_enable_switch ( true ) ;
107110 self . home_row_expander . set_enable_expansion ( false ) ;
108111 self . home_row_expander . add_row ( & home_row) ;
109112 let obj = self . obj ( ) . clone ( ) ;
110- self . home_row_expander . connect_enable_expansion_notify ( clone ! (
111- #[ weak]
112- home_row,
113- move |expander| {
114- if !expander. enables_expansion( ) {
115- obj. set_home_folder( None :: <& str >) ;
113+ self . home_row_expander
114+ . connect_enable_expansion_notify ( clone ! (
115+ #[ weak]
116+ home_row,
117+ move |expander| {
118+ if !expander. enables_expansion( ) {
119+ obj. set_home_folder( None :: <& str >) ;
120+ }
121+ home_row. set_subtitle( obj. home_folder( ) . as_deref( ) . unwrap_or( "" ) ) ;
116122 }
117- home_row. set_subtitle( obj. home_folder( ) . as_deref( ) . unwrap_or( "" ) ) ;
118- }
119- ) ) ;
123+ ) ) ;
120124
121125 let nvidia_row = adw:: SwitchRow :: new ( ) ;
122126 nvidia_row. set_title ( "NVIDIA Support" ) ;
@@ -142,13 +146,13 @@ mod imp {
142146 #[ weak]
143147 obj,
144148 move |_| {
145- let res = obj . update_create_args ( ) ;
146- obj. update_errors ( & res ) ;
147- if let Ok ( ( ) ) = res {
148- obj . root_store ( ) . create_container (
149- obj. imp ( ) . current_create_args . borrow ( ) . clone ( ) ,
150- ) ;
151- }
149+ glib :: MainContext :: ref_thread_default ( ) . spawn_local ( async move {
150+ let res = obj. extract_create_args ( ) . await ;
151+ obj . update_errors ( & res) ;
152+ if let Ok ( create_args ) = res {
153+ obj. root_store ( ) . create_container ( create_args ) ;
154+ }
155+ } ) ;
152156 }
153157 ) ) ;
154158 create_btn. add_css_class ( "suggested-action" ) ;
@@ -169,9 +173,13 @@ mod imp {
169173 assemble_group. set_description ( Some ( "Create a container from an assemble file" ) ) ;
170174
171175 let obj = self . obj ( ) . clone ( ) ;
172- let file_row = self . obj ( ) . build_file_row ( "Select Assemble File" , FileRowSelection :: File , move |path| {
173- obj. set_assemble_file ( Some ( path. display ( ) . to_string ( ) ) ) ;
174- } ) ;
176+ let file_row = self . obj ( ) . build_file_row (
177+ "Select Assemble File" ,
178+ FileRowSelection :: File ,
179+ move |path| {
180+ obj. set_assemble_file ( Some ( path. display ( ) . to_string ( ) ) ) ;
181+ } ,
182+ ) ;
175183 assemble_group. add ( & file_row) ;
176184 assemble_page. append ( & assemble_group) ;
177185
@@ -202,8 +210,6 @@ mod imp {
202210 create_btn. set_sensitive ( obj. assemble_file ( ) . is_some ( ) ) ;
203211 } ) ;
204212
205-
206-
207213 // Create page for URL creation
208214 let url_page = gtk:: Box :: new ( gtk:: Orientation :: Vertical , 12 ) ;
209215 url_page. set_margin_start ( 12 ) ;
@@ -246,7 +252,8 @@ mod imp {
246252 #[ weak]
247253 obj,
248254 move |_| {
249- obj. root_store( ) . assemble_container( & obj. assemble_url( ) . as_ref( ) . unwrap( ) ) ;
255+ obj. root_store( )
256+ . assemble_container( & obj. assemble_url( ) . as_ref( ) . unwrap( ) ) ;
250257 obj. close( ) ;
251258 }
252259 ) ) ;
@@ -255,7 +262,6 @@ mod imp {
255262 create_btn. set_sensitive ( obj. assemble_url ( ) . is_some ( ) ) ;
256263 } ) ;
257264
258-
259265 // Add pages to view stack
260266 view_stack. add_titled ( & gui_page, Some ( "create" ) , "Guided" ) ;
261267 view_stack. add_titled ( & assemble_page, Some ( "assemble-file" ) , "From File" ) ;
@@ -327,58 +333,53 @@ impl CreateDistroboxDialog {
327333 this
328334 }
329335
330- pub fn build_file_row ( & self , title : & str , selection : FileRowSelection , cb : impl Fn ( PathBuf ) + Clone + ' static ) -> adw:: ActionRow {
331- let row = adw:: ActionRow :: new ( ) ;
332- row. set_title ( title) ;
333- row. set_subtitle ( "No file selected" ) ;
334- row. set_activatable ( true ) ;
335-
336- let file_icon = gtk:: Image :: from_icon_name ( "document-open-symbolic" ) ;
337- row. add_suffix ( & file_icon) ;
338-
339- let title = title. to_owned ( ) ;
340- let dialog_cb = clone ! (
341- #[ weak]
342- row,
343- move |res: Result <File , _>| {
344- if let Ok ( file) = res {
345- if let Some ( path) = file. path( ) {
346- row. set_subtitle( & path. display( ) . to_string( ) ) ;
347- cb( path) ;
348- }
349- }
350- }
351- ) ;
352- row. connect_activated (
353- move |_| {
354- let file_dialog = gtk:: FileDialog :: builder ( )
355- . title ( & title)
356- . modal ( true )
357- . build ( ) ;
358- let dialog_cb = dialog_cb. clone ( ) ;
359- match selection {
360- FileRowSelection :: File => {
361- file_dialog. open (
362- None :: < & gtk:: Window > ,
363- None :: < & gio:: Cancellable > ,
364- dialog_cb,
365- ) ;
366- }
367- FileRowSelection :: Folder => {
368- file_dialog. select_folder (
369- None :: < & gtk:: Window > ,
370- None :: < & gio:: Cancellable > ,
371- dialog_cb,
372- ) ;
373- }
336+ pub fn build_file_row (
337+ & self ,
338+ title : & str ,
339+ selection : FileRowSelection ,
340+ cb : impl Fn ( PathBuf ) + Clone + ' static ,
341+ ) -> adw:: ActionRow {
342+ let row = adw:: ActionRow :: new ( ) ;
343+ row. set_title ( title) ;
344+ row. set_subtitle ( "No file selected" ) ;
345+ row. set_activatable ( true ) ;
346+
347+ let file_icon = gtk:: Image :: from_icon_name ( "document-open-symbolic" ) ;
348+ row. add_suffix ( & file_icon) ;
349+
350+ let title = title. to_owned ( ) ;
351+ let dialog_cb = clone ! (
352+ #[ weak]
353+ row,
354+ move |res: Result <File , _>| {
355+ if let Ok ( file) = res {
356+ if let Some ( path) = file. path( ) {
357+ row. set_subtitle( & path. display( ) . to_string( ) ) ;
358+ cb( path) ;
374359 }
375360 }
376- ) ;
377- row
378-
361+ }
362+ ) ;
363+ row. connect_activated ( move |_| {
364+ let file_dialog = gtk:: FileDialog :: builder ( ) . title ( & title) . modal ( true ) . build ( ) ;
365+ let dialog_cb = dialog_cb. clone ( ) ;
366+ match selection {
367+ FileRowSelection :: File => {
368+ file_dialog. open ( None :: < & gtk:: Window > , None :: < & gio:: Cancellable > , dialog_cb) ;
369+ }
370+ FileRowSelection :: Folder => {
371+ file_dialog. select_folder (
372+ None :: < & gtk:: Window > ,
373+ None :: < & gio:: Cancellable > ,
374+ dialog_cb,
375+ ) ;
376+ }
377+ }
378+ } ) ;
379+ row
379380 }
380381
381- pub fn update_create_args ( & self ) -> Result < ( ) , Error > {
382+ pub async fn extract_create_args ( & self ) -> Result < CreateArgs , Error > {
382383 let imp = self . imp ( ) ;
383384 let image = imp
384385 . image_row
@@ -393,32 +394,45 @@ impl CreateDistroboxDialog {
393394 . iter ( )
394395 . filter_map ( |entry| {
395396 if !entry. text ( ) . is_empty ( ) {
396- Some ( entry. text ( ) . to_string ( ) )
397+ match entry. text ( ) . parse :: < distrobox:: Volume > ( ) {
398+ Ok ( volume) => Some ( Ok ( volume) ) ,
399+ Err ( e) => Some ( Err ( e) ) ,
400+ }
397401 } else {
398402 None
399403 }
400404 } )
401- . collect :: < Vec < _ > > ( ) ;
405+ . collect :: < Result < Vec < _ > , _ > > ( ) ? ;
402406
403407 let name = CreateArgName :: new ( & imp. name_row . text ( ) ) ?;
404408
409+ dbg ! ( & self . home_folder( ) ) ;
405410 let create_args = CreateArgs {
406411 name,
407412 image : image. to_string ( ) ,
408413 nvidia : imp. nvidia_row . is_active ( ) ,
409- home_path : self . home_folder ( ) ,
414+ home_path : if let Some ( home) = self . home_folder ( ) {
415+ Some (
416+ self . root_store ( )
417+ . resolve_host_path ( & home)
418+ . await
419+ . map_err ( |e| Error :: InvalidField ( "home" . to_string ( ) , e. to_string ( ) ) ) ?,
420+ )
421+ } else {
422+ None
423+ } ,
410424 init : imp. init_row . is_active ( ) ,
411425 volumes,
412426 } ;
427+ dbg ! ( & create_args) ;
413428
414- self . imp ( ) . current_create_args . replace ( create_args) ;
415- Ok ( ( ) )
429+ Ok ( create_args)
416430 }
417431
418432 pub fn build_volumes_group ( & self ) -> adw:: PreferencesGroup {
419433 let volumes_group = adw:: PreferencesGroup :: new ( ) ;
420434 volumes_group. set_title ( "Volumes" ) ;
421- volumes_group. set_description ( Some ( "Specify volumes in the format 'dest_dir:source_dir '" ) ) ;
435+ volumes_group. set_description ( Some ( "Specify volumes in the format 'host_path:container_path '" ) ) ;
422436
423437 let add_volume_button = adw:: ButtonRow :: builder ( ) . title ( "Add Volume" ) . build ( ) ;
424438 add_volume_button. connect_activated ( clone ! (
@@ -462,10 +476,13 @@ impl CreateDistroboxDialog {
462476 volumes_group
463477 }
464478
465- fn update_errors ( & self , res : & Result < ( ) , distrobox:: Error > ) {
479+ fn update_errors < T > ( & self , res : & Result < T , distrobox:: Error > ) {
466480 let imp = self . imp ( ) ;
467481 imp. name_row . remove_css_class ( "error" ) ;
468482 imp. name_row . set_tooltip_text ( None ) ;
483+ if let Err ( ref e) = res {
484+ error ! ( error = %e, "CreateDistroboxDialog: update_errors" ) ;
485+ }
469486 match res {
470487 Err ( distrobox:: Error :: InvalidField ( field, msg) ) if field == "name" => {
471488 imp. name_row . add_css_class ( "error" ) ;
0 commit comments