Give saving its own page, with the two settings that had no control

General had become three unrelated controls: a language picker, a save format
and a file association. The last two move to an Open and Save page, where
they join the two saving preferences that have never had a widget.

Automatic save has worked since the SAVETIME command was added and is
persisted; the only way to change the interval was to type it. Same for the
`.bak` copy from #205 and its ISAVEBAK command. Both are settings people
expect to find in a dialog, and neither was in one.

The page also carries a button through to the Plot dialog. Options holds the
preferences; the plot device, paper and plot styles stay where they already
work well. Note that the modal stack shows one dialog at a time, so the
button replaces Options rather than stacking on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
PanosandClaude Opus 5 committed 2026-09-10 08:22:36 +03:00
1 parent b1d2ac2744
commit ec8d733857
4 files changed
+96 -2

No files matched your search

+4
View File
@@ -2007,6 +2007,10 @@ pub enum Message {
ShiftToAddToggled(bool),
/// Toggle press-and-drag drawing a rectangle instead of a lasso (PICKDRAG).
PickDragRectToggled(bool),
/// Change the automatic-save interval in minutes; 0 disables it (SAVETIME).
SaveTimeChanged(i32),
/// Toggle keeping a `.bak` copy when overwriting a drawing (ISAVEBAK).
BackupOnSaveChanged(bool),
/// Restore Model Space display/canvas appearance to defaults.
RestoreModelSpaceDisplayDefaults,
/// Restore Selection visual effect settings to defaults.
+12
View File
@@ -6188,6 +6188,18 @@ impl OpenCADStudio {
Task::none()
}
Message::SaveTimeChanged(minutes) => {
self.savetime_min = minutes.max(0);
self.persist_settings_if_changed();
Task::none()
}
Message::BackupOnSaveChanged(enabled) => {
self.backup_on_save = enabled;
self.persist_settings_if_changed();
Task::none()
}
Message::PickDragRectToggled(rectangle) => {
self.pick_drag_rect = rectangle;
self.persist_settings_if_changed();
+4
View File
@@ -192,6 +192,10 @@ impl OpenCADStudio {
pick_drag_rect: self.pick_drag_rect,
grip_object_limit: self.grip_object_limit,
},
crate::ui::window::options::AppPrefs {
savetime_min: self.savetime_min,
backup_on_save: self.backup_on_save,
},
self.double_click_block_refedit,
self.double_click_block_attedit,
self.cursor_type,
+76 -2
View File
@@ -25,11 +25,25 @@ const DIALOG_HEIGHT: f32 = 620.0;
pub enum OptionsTab {
#[default]
General,
OpenAndSave,
Display,
Selection,
Drawing,
}
/// Application preferences the dialog reads that are plain scalars on the app.
///
/// Gathered rather than passed one by one: `view_window` already carries a
/// long positional list, and several of these are adjacent `bool`s that would
/// swap silently at the call site.
#[derive(Clone, Copy)]
pub struct AppPrefs {
/// SAVETIME, minutes between recovery saves; 0 disables.
pub savetime_min: i32,
/// ISAVEBAK: keep a `.bak` when overwriting.
pub backup_on_save: bool,
}
/// The Selection-card settings that live on `UserSettings` rather than on the
/// model-space theme.
///
@@ -70,6 +84,7 @@ pub fn view_window<'a>(
active_tab: OptionsTab,
cursor_size: i32,
selection: SelectionPrefs,
prefs: AppPrefs,
double_click_block_refedit: bool,
double_click_block_attedit: bool,
cursor_type: CursorType,
@@ -187,8 +202,18 @@ pub fn view_window<'a>(
]
.spacing(12)
.align_y(iced::Center),
Space::new().height(22),
text(crate::tr!("options", "open-save-section")).size(15),
]
.spacing(0)
.width(sizing.width);
// Saving preferences, gathered onto one page. The format and the file
// association were on General, which had become a page of three unrelated
// controls; the autosave interval and the backup toggle have existed since
// #205 with no control at all.
let open_and_save = column![
text(crate::t!("Open and Save")).size(15),
Space::new().height(10),
Space::new().height(10),
row![
text(crate::tr!("options", "default-save-format-label")).size(12).width(150),
@@ -222,6 +247,53 @@ pub fn view_window<'a>(
))
.size(11)
.width(sizing.width),
Space::new().height(22),
text(crate::t!("File Safety")).size(15),
Space::new().height(10),
row![
text(crate::t!("Automatic save")).size(12).width(150),
slider(0..=120, prefs.savetime_min.clamp(0, 120), Message::SaveTimeChanged)
.step(1)
.width(Fill),
text(if prefs.savetime_min <= 0 {
crate::t!("Off").into_owned()
} else {
format!("{} min", prefs.savetime_min)
})
.size(11)
.width(52),
]
.spacing(10)
.align_y(iced::Center),
Space::new().height(6),
text(crate::t!(
"Minutes between recovery saves to a .sv$ file; 0 turns it off (SAVETIME)."
))
.size(11)
.width(sizing.width),
Space::new().height(14),
row![
iced::widget::checkbox(prefs.backup_on_save)
.on_toggle(Message::BackupOnSaveChanged)
.size(15),
text(crate::t!("Keep a .bak copy when overwriting a drawing (ISAVEBAK)")).size(12),
]
.spacing(8)
.align_y(iced::Center),
Space::new().height(22),
text(crate::t!("Plotting")).size(15),
Space::new().height(10),
row![
text(crate::t!("Plot device, paper, scale and plot styles"))
.size(12)
.width(Fill),
button(text(crate::t!("Plot and Page Setup…")).size(11))
.on_press(Message::PlotDialogOpen)
.padding([4, 10])
.style(button::secondary),
]
.spacing(10)
.align_y(iced::Center),
]
.spacing(0)
.width(sizing.width);
@@ -852,6 +924,7 @@ pub fn view_window<'a>(
OptionsTab::General => general.into(),
OptionsTab::Display => display_element.into(),
OptionsTab::Selection => selection.into(),
OptionsTab::OpenAndSave => open_and_save.into(),
OptionsTab::Drawing => drawing.into(),
};
@@ -868,6 +941,7 @@ pub fn view_window<'a>(
};
let tabs = column![
tab_button(crate::t!("General"), OptionsTab::General),
tab_button(crate::t!("Open and Save"), OptionsTab::OpenAndSave),
tab_button(crate::t!("Display"), OptionsTab::Display),
tab_button(crate::t!("Selection"), OptionsTab::Selection),
tab_button(crate::t!("Drawing"), OptionsTab::Drawing),