breadman: rebuild settings with libadwaita components
Proof-of-concept for the ecosystem-wide design-system work: every setting
is now an AdwPreferencesGroup/SwitchRow/SpinRow/ActionRow/ComboRow via
bread-theme::adw, instead of a hand-rolled GtkGrid of labels + raw widgets.
This directly fixes the two worst defects a design critique found here:
- Toggle switches rendered ~1400px wide, like progress bars — caused by
GtkGrid sizing a switch's column to match a sibling entry's hexpand in
the same grid, and Switch has no default that resists filling that
width. AdwSwitchRow owns its own layout, so this class of bug can't
recur.
- Spin buttons were ~1300px from the label they modified, for the same
grid-column-sizing reason. AdwSpinRow docks the spinner to its title.
Also softened the jargon-forward section titles the critique flagged
("Model (Tier 2 ONNX)", "Ollama (Tier 3)") — the tier/implementation
detail moved from the title (loud, unavoidable) to each group's
description (quieter, still there for anyone who wants it).
bread-theme now needs a direct dependency here (branch=dev, `adw`
feature) since breadpad-shared's own bread-theme dependency is tag-pinned
to a release before this feature existed.
This commit is contained in:
parent
b8a37cbb85
commit
b85d682721
4 changed files with 189 additions and 143 deletions
70
Cargo.lock
generated
70
Cargo.lock
generated
|
|
@ -76,7 +76,7 @@ version = "1.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -87,7 +87,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -305,7 +305,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "bread-screenshots"
|
||||
version = "0.3.1"
|
||||
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?branch=dev#1a3475bd2358202f60e29c9bd27d06b1428b1a27"
|
||||
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?branch=dev#4e76bc707720fbfc52e19a8cc78f3fb1e6e0a713"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bread-utils",
|
||||
|
|
@ -323,10 +323,22 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bread-theme"
|
||||
version = "0.3.1"
|
||||
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?branch=dev#4e76bc707720fbfc52e19a8cc78f3fb1e6e0a713"
|
||||
dependencies = [
|
||||
"dirs 5.0.1",
|
||||
"gtk4",
|
||||
"libadwaita",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bread-utils"
|
||||
version = "0.3.1"
|
||||
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?branch=dev#1a3475bd2358202f60e29c9bd27d06b1428b1a27"
|
||||
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?branch=dev#4e76bc707720fbfc52e19a8cc78f3fb1e6e0a713"
|
||||
dependencies = [
|
||||
"dirs 5.0.1",
|
||||
"serde",
|
||||
|
|
@ -339,11 +351,13 @@ version = "0.3.4"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"bread-screenshots",
|
||||
"bread-theme 0.3.1",
|
||||
"breadpad-shared",
|
||||
"chrono",
|
||||
"dirs 5.0.1",
|
||||
"futures-channel",
|
||||
"gtk4",
|
||||
"libadwaita",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
@ -376,7 +390,7 @@ name = "breadpad-shared"
|
|||
version = "0.3.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bread-theme",
|
||||
"bread-theme 0.2.3",
|
||||
"chrono",
|
||||
"dirs 5.0.1",
|
||||
"ical",
|
||||
|
|
@ -873,7 +887,7 @@ dependencies = [
|
|||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -948,7 +962,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1259,7 +1273,7 @@ dependencies = [
|
|||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1879,6 +1893,36 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||
|
||||
[[package]]
|
||||
name = "libadwaita"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85b9900e67182a4b5b1f157b448d94f0715c8b9770cce21cf000801917f53bfa"
|
||||
dependencies = [
|
||||
"gdk4",
|
||||
"gio",
|
||||
"glib",
|
||||
"gtk4",
|
||||
"libadwaita-sys",
|
||||
"pango",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libadwaita-sys"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3c27642b389852aa99341bd4a4c19ec6f8a2b63ebdd7f5ba1952198079ccd"
|
||||
dependencies = [
|
||||
"gdk4-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gtk4-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
|
|
@ -2101,7 +2145,7 @@ version = "0.50.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2723,7 +2767,7 @@ dependencies = [
|
|||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2937,7 +2981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3047,7 +3091,7 @@ dependencies = [
|
|||
"getrandom 0.4.2",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3415,7 +3459,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
|||
dependencies = [
|
||||
"memoffset",
|
||||
"tempfile",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ path = "src/main.rs"
|
|||
breadpad-shared = { path = "../breadpad-shared" }
|
||||
# Capture primitives for `--screenshot` mode — see src/screenshot.rs.
|
||||
bread-screenshots = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", branch = "dev" }
|
||||
# libadwaita-based settings-screen components (see src/views/settings.rs) —
|
||||
# on "dev", not breadpad-shared's tag-pinned copy, since the `adw` feature
|
||||
# doesn't exist on a tagged release yet.
|
||||
bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", branch = "dev", features = ["adw"] }
|
||||
libadwaita = { version = "0.9", features = ["v1_7"] }
|
||||
anyhow.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
|
|
|
|||
|
|
@ -342,6 +342,10 @@ fn build_app_window(
|
|||
screenshot_req: Option<screenshot::ScreenshotRequest>,
|
||||
) -> Result<()> {
|
||||
apply_css(&cfg);
|
||||
// Needed once before constructing any adw:: widget (see views::settings) —
|
||||
// also forces dark mode, since bread-theme's palette is a fixed dark base
|
||||
// regardless of the system GTK preference.
|
||||
bread_theme::adw::init();
|
||||
|
||||
let store = Arc::new(Store::new()?);
|
||||
let notes = store.load_all()?;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use breadpad_shared::config::{
|
||||
CalendarConfig, Config, ModelConfig, OllamaConfig, RemindersConfig, Settings,
|
||||
};
|
||||
use bread_theme::adw;
|
||||
use gtk4::prelude::*;
|
||||
use libadwaita::prelude::*;
|
||||
|
||||
pub fn build(cfg: &Config, on_save: impl Fn(Config) + 'static) -> gtk4::ScrolledWindow {
|
||||
let scroll = gtk4::ScrolledWindow::builder()
|
||||
|
|
@ -10,139 +12,148 @@ pub fn build(cfg: &Config, on_save: impl Fn(Config) + 'static) -> gtk4::Scrolled
|
|||
.vexpand(true)
|
||||
.build();
|
||||
|
||||
let outer = gtk4::Box::builder()
|
||||
.orientation(gtk4::Orientation::Vertical)
|
||||
.spacing(16)
|
||||
.margin_top(16)
|
||||
.margin_bottom(16)
|
||||
.margin_start(16)
|
||||
.margin_end(16)
|
||||
.build();
|
||||
let page = libadwaita::PreferencesPage::new();
|
||||
|
||||
// ── General ──────────────────────────────────────────────────
|
||||
let (general_frame, general_grid) = make_section("General");
|
||||
let general_group = adw::preferences_group("General", None);
|
||||
|
||||
let type_options = ["note", "todo", "reminder", "idea", "question"];
|
||||
let default_type_combo = gtk4::DropDown::from_strings(&type_options);
|
||||
let default_type_row = libadwaita::ComboRow::builder()
|
||||
.title("Default type")
|
||||
.model(>k4::StringList::new(&type_options))
|
||||
.build();
|
||||
let dt_idx = type_options
|
||||
.iter()
|
||||
.position(|&s| s == cfg.settings.default_type.as_str())
|
||||
.unwrap_or(0) as u32;
|
||||
default_type_combo.set_selected(dt_idx);
|
||||
attach_row(&general_grid, 0, "Default type", &default_type_combo);
|
||||
default_type_row.set_selected(dt_idx);
|
||||
general_group.add(&default_type_row);
|
||||
|
||||
let ws_tag_switch = gtk4::Switch::builder()
|
||||
.active(cfg.settings.workspace_tag)
|
||||
let ws_tag_row = adw::toggle_row(
|
||||
"Workspace tag",
|
||||
Some("Tag new notes with the Hyprland workspace they were created on"),
|
||||
cfg.settings.workspace_tag,
|
||||
);
|
||||
general_group.add(&ws_tag_row);
|
||||
|
||||
let archive_adj = gtk4::Adjustment::new(cfg.settings.archive_after_days as f64, 1.0, 365.0, 1.0, 7.0, 0.0);
|
||||
let archive_row = adw::spin_row("Archive after (days)", None, &archive_adj);
|
||||
general_group.add(&archive_row);
|
||||
|
||||
let snooze_row = adw::action_row("Snooze options", Some("Comma-separated (e.g. 15m, 1h, tomorrow_morning)"));
|
||||
let snooze_entry = gtk4::Entry::builder()
|
||||
.text(cfg.settings.snooze_options.join(", "))
|
||||
.valign(gtk4::Align::Center)
|
||||
.build();
|
||||
attach_row(&general_grid, 1, "Workspace tag", &ws_tag_switch);
|
||||
snooze_row.add_suffix(&snooze_entry);
|
||||
general_group.add(&snooze_row);
|
||||
|
||||
let archive_spin = gtk4::SpinButton::with_range(1.0, 365.0, 1.0);
|
||||
archive_spin.set_value(cfg.settings.archive_after_days as f64);
|
||||
attach_row(&general_grid, 2, "Archive after (days)", &archive_spin);
|
||||
|
||||
let snooze_entry = gtk4::Entry::builder()
|
||||
.text(&cfg.settings.snooze_options.join(", "))
|
||||
.hexpand(true)
|
||||
.build();
|
||||
attach_row(&general_grid, 3, "Snooze options", &snooze_entry);
|
||||
|
||||
outer.append(&general_frame);
|
||||
page.add(&general_group);
|
||||
|
||||
// ── Reminders ────────────────────────────────────────────────
|
||||
let (rem_frame, rem_grid) = make_section("Reminders");
|
||||
let rem_group = adw::preferences_group("Reminders", None);
|
||||
|
||||
let morning_row = adw::action_row("Default morning", Some("Used for \"tomorrow_morning\" snoozes and recurring reminders"));
|
||||
let morning_entry = gtk4::Entry::builder()
|
||||
.text(&cfg.reminders.default_morning)
|
||||
.placeholder_text("HH:MM")
|
||||
.build();
|
||||
attach_row(&rem_grid, 0, "Default morning", &morning_entry);
|
||||
|
||||
let grace_spin = gtk4::SpinButton::with_range(0.0, 1440.0, 5.0);
|
||||
grace_spin.set_value(cfg.reminders.missed_grace_minutes as f64);
|
||||
attach_row(&rem_grid, 1, "Missed grace (minutes)", &grace_spin);
|
||||
|
||||
outer.append(&rem_frame);
|
||||
|
||||
// ── Model ─────────────────────────────────────────────────────
|
||||
let (model_frame, model_grid) = make_section("Model (Tier 2 ONNX)");
|
||||
|
||||
let model_path_entry = gtk4::Entry::builder()
|
||||
.text(&cfg.model.path)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
attach_row(&model_grid, 0, "ONNX path", &model_path_entry);
|
||||
|
||||
let tokenizer_entry = gtk4::Entry::builder()
|
||||
.text(&cfg.model.tokenizer)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
attach_row(&model_grid, 1, "Tokenizer path", &tokenizer_entry);
|
||||
|
||||
let ort_dylib_entry = gtk4::Entry::builder()
|
||||
.text(&cfg.model.ort_dylib_path)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
attach_row(&model_grid, 2, "ORT dylib path", &ort_dylib_entry);
|
||||
|
||||
outer.append(&model_frame);
|
||||
|
||||
// ── Ollama (Tier 3) ───────────────────────────────────────────
|
||||
let (ollama_frame, ollama_grid) = make_section("Ollama (Tier 3)");
|
||||
|
||||
let ollama_enabled = gtk4::Switch::builder()
|
||||
.active(cfg.model.ollama.enabled)
|
||||
.valign(gtk4::Align::Center)
|
||||
.build();
|
||||
attach_row(&ollama_grid, 0, "Enabled", &ollama_enabled);
|
||||
morning_row.add_suffix(&morning_entry);
|
||||
rem_group.add(&morning_row);
|
||||
|
||||
let ollama_endpoint = gtk4::Entry::builder()
|
||||
.text(&cfg.model.ollama.endpoint)
|
||||
.hexpand(true)
|
||||
.build();
|
||||
attach_row(&ollama_grid, 1, "Endpoint", &ollama_endpoint);
|
||||
let grace_adj = gtk4::Adjustment::new(cfg.reminders.missed_grace_minutes as f64, 0.0, 1440.0, 5.0, 30.0, 0.0);
|
||||
let grace_row = adw::spin_row("Missed grace (minutes)", Some("How late a reminder can fire before it's considered missed"), &grace_adj);
|
||||
rem_group.add(&grace_row);
|
||||
|
||||
let ollama_model = gtk4::Entry::builder()
|
||||
.text(&cfg.model.ollama.model)
|
||||
.build();
|
||||
attach_row(&ollama_grid, 2, "Model", &ollama_model);
|
||||
page.add(&rem_group);
|
||||
|
||||
let ollama_thresh = gtk4::SpinButton::with_range(0.0, 1.0, 0.05);
|
||||
ollama_thresh.set_value(cfg.model.ollama.confidence_threshold as f64);
|
||||
ollama_thresh.set_digits(2);
|
||||
attach_row(&ollama_grid, 3, "Confidence threshold", &ollama_thresh);
|
||||
// ── Local classifier ───────────────────────────────────────────
|
||||
let model_group = adw::preferences_group(
|
||||
"Local Classifier",
|
||||
Some("Optional local ONNX model for classifying note type/time without a network round-trip."),
|
||||
);
|
||||
|
||||
outer.append(&ollama_frame);
|
||||
let model_path_row = adw::action_row("Model path", None);
|
||||
let model_path_entry = gtk4::Entry::builder().text(&cfg.model.path).hexpand(true).width_chars(36).valign(gtk4::Align::Center).build();
|
||||
model_path_row.add_suffix(&model_path_entry);
|
||||
model_group.add(&model_path_row);
|
||||
|
||||
// ── Calendar ─────────────────────────────────────────────────
|
||||
let (cal_frame, cal_grid) = make_section("Nextcloud Calendar (CalDAV)");
|
||||
let tokenizer_row = adw::action_row("Tokenizer path", None);
|
||||
let tokenizer_entry = gtk4::Entry::builder().text(&cfg.model.tokenizer).hexpand(true).width_chars(36).valign(gtk4::Align::Center).build();
|
||||
tokenizer_row.add_suffix(&tokenizer_entry);
|
||||
model_group.add(&tokenizer_row);
|
||||
|
||||
let cal_enabled = gtk4::Switch::builder()
|
||||
.active(cfg.calendar.enabled)
|
||||
.valign(gtk4::Align::Center)
|
||||
.build();
|
||||
attach_row(&cal_grid, 0, "Enabled", &cal_enabled);
|
||||
let ort_dylib_row = adw::action_row("Runtime library path", None);
|
||||
let ort_dylib_entry = gtk4::Entry::builder().text(&cfg.model.ort_dylib_path).hexpand(true).width_chars(36).valign(gtk4::Align::Center).build();
|
||||
ort_dylib_row.add_suffix(&ort_dylib_entry);
|
||||
model_group.add(&ort_dylib_row);
|
||||
|
||||
page.add(&model_group);
|
||||
|
||||
// ── AI classification (Ollama) ──────────────────────────────────
|
||||
let ollama_group = adw::preferences_group(
|
||||
"AI Classification",
|
||||
Some("Uses a local Ollama model as a fallback classifier when the ONNX model is unavailable or unsure."),
|
||||
);
|
||||
|
||||
let ollama_enabled_row = adw::toggle_row("Enabled", None, cfg.model.ollama.enabled);
|
||||
ollama_group.add(&ollama_enabled_row);
|
||||
|
||||
let ollama_endpoint_row = adw::action_row("Endpoint", None);
|
||||
let ollama_endpoint_entry = gtk4::Entry::builder().text(&cfg.model.ollama.endpoint).hexpand(true).width_chars(36).valign(gtk4::Align::Center).build();
|
||||
ollama_endpoint_row.add_suffix(&ollama_endpoint_entry);
|
||||
ollama_group.add(&ollama_endpoint_row);
|
||||
|
||||
let ollama_model_row = adw::action_row("Model", None);
|
||||
let ollama_model_entry = gtk4::Entry::builder().text(&cfg.model.ollama.model).valign(gtk4::Align::Center).build();
|
||||
ollama_model_row.add_suffix(&ollama_model_entry);
|
||||
ollama_group.add(&ollama_model_row);
|
||||
|
||||
let ollama_thresh_adj = gtk4::Adjustment::new(cfg.model.ollama.confidence_threshold as f64, 0.0, 1.0, 0.05, 0.1, 0.0);
|
||||
let ollama_thresh_row = adw::spin_row("Confidence threshold", None, &ollama_thresh_adj);
|
||||
if let Some(spin) = ollama_thresh_row.first_child().and_downcast::<gtk4::SpinButton>() {
|
||||
spin.set_digits(2);
|
||||
}
|
||||
ollama_group.add(&ollama_thresh_row);
|
||||
|
||||
page.add(&ollama_group);
|
||||
|
||||
// ── Calendar sync ────────────────────────────────────────────
|
||||
let cal_group = adw::preferences_group(
|
||||
"Calendar Sync",
|
||||
Some("Sync reminders to a Nextcloud calendar via CalDAV."),
|
||||
);
|
||||
|
||||
let cal_enabled_row = adw::toggle_row("Enabled", None, cfg.calendar.enabled);
|
||||
cal_group.add(&cal_enabled_row);
|
||||
|
||||
let cal_url_row = adw::action_row("Calendar URL", None);
|
||||
let cal_url = gtk4::Entry::builder()
|
||||
.text(&cfg.calendar.url)
|
||||
.placeholder_text("https://nextcloud.example.com/remote.php/dav/calendars/you/personal/")
|
||||
.hexpand(true)
|
||||
.width_chars(36)
|
||||
.valign(gtk4::Align::Center)
|
||||
.build();
|
||||
attach_row(&cal_grid, 1, "Calendar URL", &cal_url);
|
||||
cal_url_row.add_suffix(&cal_url);
|
||||
cal_group.add(&cal_url_row);
|
||||
|
||||
let cal_user = gtk4::Entry::builder()
|
||||
.text(&cfg.calendar.username)
|
||||
.build();
|
||||
attach_row(&cal_grid, 2, "Username", &cal_user);
|
||||
let cal_user_row = adw::action_row("Username", None);
|
||||
let cal_user = gtk4::Entry::builder().text(&cfg.calendar.username).valign(gtk4::Align::Center).build();
|
||||
cal_user_row.add_suffix(&cal_user);
|
||||
cal_group.add(&cal_user_row);
|
||||
|
||||
let cal_pass = gtk4::Entry::builder()
|
||||
let cal_pass_row = adw::action_row("App password", None);
|
||||
let cal_pass = gtk4::PasswordEntry::builder()
|
||||
.text(&cfg.calendar.password)
|
||||
.input_purpose(gtk4::InputPurpose::Password)
|
||||
.visibility(false)
|
||||
.show_peek_icon(true)
|
||||
.valign(gtk4::Align::Center)
|
||||
.build();
|
||||
attach_row(&cal_grid, 3, "App password", &cal_pass);
|
||||
cal_pass_row.add_suffix(&cal_pass);
|
||||
cal_group.add(&cal_pass_row);
|
||||
|
||||
outer.append(&cal_frame);
|
||||
page.add(&cal_group);
|
||||
|
||||
// ── Save ──────────────────────────────────────────────────────
|
||||
let status_label = gtk4::Label::builder()
|
||||
|
|
@ -157,20 +168,20 @@ pub fn build(cfg: &Config, on_save: impl Fn(Config) + 'static) -> gtk4::Scrolled
|
|||
.build();
|
||||
|
||||
{
|
||||
let dtc = default_type_combo.clone();
|
||||
let wts = ws_tag_switch.clone();
|
||||
let ars = archive_spin.clone();
|
||||
let dtc = default_type_row.clone();
|
||||
let wts = ws_tag_row.clone();
|
||||
let ars = archive_adj.clone();
|
||||
let sne = snooze_entry.clone();
|
||||
let moe = morning_entry.clone();
|
||||
let grs = grace_spin.clone();
|
||||
let grs = grace_adj.clone();
|
||||
let mpe = model_path_entry.clone();
|
||||
let tke = tokenizer_entry.clone();
|
||||
let ode = ort_dylib_entry.clone();
|
||||
let oec = ollama_enabled.clone();
|
||||
let oee = ollama_endpoint.clone();
|
||||
let ome = ollama_model.clone();
|
||||
let ots = ollama_thresh.clone();
|
||||
let cec = cal_enabled.clone();
|
||||
let oec = ollama_enabled_row.clone();
|
||||
let oee = ollama_endpoint_entry.clone();
|
||||
let ome = ollama_model_entry.clone();
|
||||
let ots = ollama_thresh_adj.clone();
|
||||
let cec = cal_enabled_row.clone();
|
||||
let cuc = cal_url.clone();
|
||||
let csc = cal_user.clone();
|
||||
let cpc = cal_pass.clone();
|
||||
|
|
@ -228,37 +239,19 @@ pub fn build(cfg: &Config, on_save: impl Fn(Config) + 'static) -> gtk4::Scrolled
|
|||
let btn_row = gtk4::Box::builder()
|
||||
.orientation(gtk4::Orientation::Horizontal)
|
||||
.spacing(8)
|
||||
.margin_top(16)
|
||||
.margin_start(16)
|
||||
.margin_end(16)
|
||||
.margin_bottom(16)
|
||||
.build();
|
||||
btn_row.append(&status_label);
|
||||
btn_row.append(>k4::Box::builder().hexpand(true).build());
|
||||
btn_row.append(&save_btn);
|
||||
|
||||
let outer = gtk4::Box::builder().orientation(gtk4::Orientation::Vertical).build();
|
||||
outer.append(&page);
|
||||
outer.append(&btn_row);
|
||||
|
||||
scroll.set_child(Some(&outer));
|
||||
scroll
|
||||
}
|
||||
|
||||
fn make_section(title: &str) -> (gtk4::Frame, gtk4::Grid) {
|
||||
let frame = gtk4::Frame::builder().label(title).build();
|
||||
let grid = gtk4::Grid::builder()
|
||||
.row_spacing(8)
|
||||
.column_spacing(16)
|
||||
.margin_top(8)
|
||||
.margin_bottom(8)
|
||||
.margin_start(8)
|
||||
.margin_end(8)
|
||||
.build();
|
||||
frame.set_child(Some(&grid));
|
||||
(frame, grid)
|
||||
}
|
||||
|
||||
fn attach_row(grid: >k4::Grid, row: i32, label: &str, widget: &impl gtk4::prelude::IsA<gtk4::Widget>) {
|
||||
let lbl = gtk4::Label::builder()
|
||||
.label(label)
|
||||
.xalign(0.0)
|
||||
.hexpand(false)
|
||||
.width_chars(24)
|
||||
.build();
|
||||
grid.attach(&lbl, 0, row, 1, 1);
|
||||
grid.attach(widget, 1, row, 1, 1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue