Enhance save preset dialog with settings summary and update option
Replace simple alert dialog with full dialog showing workflow summary, new preset name entry, and option to update existing user presets. Never overwrites built-in presets.
This commit is contained in:
@@ -2047,40 +2047,128 @@ fn import_preset(window: &adw::ApplicationWindow, ui: &WizardUi) {
|
||||
}
|
||||
|
||||
fn save_preset_dialog(window: &adw::ApplicationWindow, ui: &WizardUi) {
|
||||
let dialog = adw::AlertDialog::builder()
|
||||
.heading("Save as Preset")
|
||||
.body("Enter a name for this workflow preset")
|
||||
let dialog = adw::Dialog::builder()
|
||||
.title("Save as Preset")
|
||||
.content_width(400)
|
||||
.content_height(500)
|
||||
.build();
|
||||
|
||||
let entry = gtk::Entry::builder()
|
||||
.placeholder_text("My Workflow")
|
||||
let toolbar = adw::ToolbarView::new();
|
||||
let header = adw::HeaderBar::new();
|
||||
toolbar.add_top_bar(&header);
|
||||
|
||||
let scrolled = gtk::ScrolledWindow::builder()
|
||||
.hscrollbar_policy(gtk::PolicyType::Never)
|
||||
.vexpand(true)
|
||||
.build();
|
||||
|
||||
let content = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Vertical)
|
||||
.spacing(12)
|
||||
.margin_top(12)
|
||||
.margin_bottom(12)
|
||||
.margin_start(24)
|
||||
.margin_end(24)
|
||||
.build();
|
||||
dialog.set_extra_child(Some(&entry));
|
||||
|
||||
dialog.add_response("cancel", "Cancel");
|
||||
dialog.add_response("save", "Save");
|
||||
dialog.set_response_appearance("save", adw::ResponseAppearance::Suggested);
|
||||
dialog.set_default_response(Some("save"));
|
||||
// Show summary of current settings
|
||||
let cfg = ui.state.job_config.borrow();
|
||||
let summary = build_preset_description(&cfg);
|
||||
drop(cfg);
|
||||
|
||||
let ui = ui.clone();
|
||||
dialog.connect_response(None, move |dlg, response| {
|
||||
if response == "save" {
|
||||
let extra = dlg.extra_child();
|
||||
let name = extra
|
||||
.as_ref()
|
||||
.and_then(|w| w.downcast_ref::<gtk::Entry>())
|
||||
.map(|e| e.text().to_string())
|
||||
.unwrap_or_default();
|
||||
let summary_group = adw::PreferencesGroup::builder()
|
||||
.title("Workflow Summary")
|
||||
.description(&summary)
|
||||
.build();
|
||||
content.append(&summary_group);
|
||||
|
||||
// Name entry
|
||||
let name_group = adw::PreferencesGroup::builder()
|
||||
.title("Save as New Preset")
|
||||
.build();
|
||||
|
||||
let name_entry = adw::EntryRow::builder()
|
||||
.title("Preset Name")
|
||||
.build();
|
||||
name_group.add(&name_entry);
|
||||
|
||||
let save_new_button = gtk::Button::builder()
|
||||
.label("Save New Preset")
|
||||
.halign(gtk::Align::Center)
|
||||
.margin_top(8)
|
||||
.build();
|
||||
save_new_button.add_css_class("suggested-action");
|
||||
save_new_button.add_css_class("pill");
|
||||
|
||||
content.append(&name_group);
|
||||
content.append(&save_new_button);
|
||||
|
||||
// "Update existing" section - show user presets
|
||||
let store = pixstrip_core::storage::PresetStore::new();
|
||||
let user_presets: Vec<String> = store
|
||||
.list()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|p| p.is_custom)
|
||||
.map(|p| p.name)
|
||||
.collect();
|
||||
|
||||
if !user_presets.is_empty() {
|
||||
let update_group = adw::PreferencesGroup::builder()
|
||||
.title("Or Update Existing Preset")
|
||||
.description("Overwrite an existing user preset with current settings")
|
||||
.build();
|
||||
|
||||
for preset_name in &user_presets {
|
||||
let row = adw::ActionRow::builder()
|
||||
.title(preset_name)
|
||||
.activatable(true)
|
||||
.build();
|
||||
row.add_prefix(>k::Image::from_icon_name("document-save-symbolic"));
|
||||
row.add_suffix(>k::Image::from_icon_name("go-next-symbolic"));
|
||||
|
||||
let ui_c = ui.clone();
|
||||
let dlg_c = dialog.clone();
|
||||
let pname = preset_name.clone();
|
||||
row.connect_activated(move |_| {
|
||||
let cfg = ui_c.state.job_config.borrow();
|
||||
let preset = build_preset_from_config(&cfg, &pname);
|
||||
drop(cfg);
|
||||
|
||||
let store = pixstrip_core::storage::PresetStore::new();
|
||||
match store.save(&preset) {
|
||||
Ok(()) => {
|
||||
let toast = adw::Toast::new(&format!("Updated preset: {}", pname));
|
||||
ui_c.toast_overlay.add_toast(toast);
|
||||
}
|
||||
Err(e) => {
|
||||
let toast = adw::Toast::new(&format!("Failed to update: {}", e));
|
||||
ui_c.toast_overlay.add_toast(toast);
|
||||
}
|
||||
}
|
||||
dlg_c.close();
|
||||
});
|
||||
|
||||
update_group.add(&row);
|
||||
}
|
||||
|
||||
content.append(&update_group);
|
||||
}
|
||||
|
||||
// Wire save new button
|
||||
{
|
||||
let ui_c = ui.clone();
|
||||
let dlg_c = dialog.clone();
|
||||
let entry_c = name_entry.clone();
|
||||
save_new_button.connect_clicked(move |_| {
|
||||
let name = entry_c.text().to_string();
|
||||
if name.trim().is_empty() {
|
||||
let toast = adw::Toast::new("Please enter a name for the preset");
|
||||
ui.toast_overlay.add_toast(toast);
|
||||
ui_c.toast_overlay.add_toast(toast);
|
||||
return;
|
||||
}
|
||||
|
||||
let cfg = ui.state.job_config.borrow();
|
||||
let cfg = ui_c.state.job_config.borrow();
|
||||
let preset = build_preset_from_config(&cfg, &name);
|
||||
drop(cfg);
|
||||
|
||||
@@ -2088,15 +2176,20 @@ fn save_preset_dialog(window: &adw::ApplicationWindow, ui: &WizardUi) {
|
||||
match store.save(&preset) {
|
||||
Ok(()) => {
|
||||
let toast = adw::Toast::new(&format!("Saved preset: {}", name));
|
||||
ui.toast_overlay.add_toast(toast);
|
||||
ui_c.toast_overlay.add_toast(toast);
|
||||
}
|
||||
Err(e) => {
|
||||
let toast = adw::Toast::new(&format!("Failed to save: {}", e));
|
||||
ui.toast_overlay.add_toast(toast);
|
||||
ui_c.toast_overlay.add_toast(toast);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
dlg_c.close();
|
||||
});
|
||||
}
|
||||
|
||||
scrolled.set_child(Some(&content));
|
||||
toolbar.set_content(Some(&scrolled));
|
||||
dialog.set_child(Some(&toolbar));
|
||||
|
||||
dialog.present(Some(window));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user