Skip to content

Commit 0952d9d

Browse files
authored
Merge pull request #26 from ranfdev/next
Next
2 parents c1390a5 + 2515802 commit 0952d9d

File tree

6 files changed

+219
-95
lines changed

6 files changed

+219
-95
lines changed

data/com.ranfdev.DistroShelf.metainfo.xml.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@
7171
</screenshots>
7272

7373
<releases>
74+
<release version="1.0.8" date="2025-05-28">
75+
<description translate="no">
76+
<ul>
77+
<li>Fixed custom home path resolution</li>
78+
<li>Add parsing of volume paths</li>
79+
</ul>
80+
</description>
81+
</release>
7482
<release version="1.0.7" date="2025-05-23">
7583
<description translate="no">
7684
<ul>

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
project('distroshelf', 'rust',
2-
version: '1.0.7',
2+
version: '1.0.8',
33
meson_version: '>= 1.0.0',
44
default_options: [ 'warning_level=2', 'werror=false', ],
55
)

src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub static VERSION: &str = "1.0.7";
1+
pub static VERSION: &str = "1.0.8";
22
pub static GETTEXT_PACKAGE: &str = "distroshelf";
33
pub static LOCALEDIR: &str = "/app/share/locale";
44
pub static PKGDATADIR: &str = "/app/share/distroshelf";

src/create_distrobox_dialog.rs

Lines changed: 101 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use adw::prelude::*;
22
use adw::subclass::prelude::*;
33
use gtk::gio::File;
44
use gtk::{gio, glib};
5+
use tracing::error;
56

67
use crate::distrobox::{self, CreateArgName, CreateArgs, Error};
78
use crate::root_store::RootStore;
@@ -15,7 +16,7 @@ use gtk::glib::{derived_properties, Properties};
1516

1617
pub enum FileRowSelection {
1718
File,
18-
Folder
19+
Folder,
1920
}
2021
mod 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

Comments
 (0)