Skip to content

[Feature]: Ask to save unsaved changes before quitting or replacing the project #906

Closed

Description

@Mavrick-F

Before you start

What problem does this solve?

The desktop app never asks before it discards unsaved changes. Quit (ui.quit sets quit_requested), the window's close button, New (Mod+N, the toolbar, the backstage), Open, the World Atlas sample, a template, a recent project, and a project dropped on the window all replace the project without a word. The app has no close_requested handling, so it can't stop a close. The browser app already warns before a page with unsaved changes is left (beforeunload).

Autosave (#873, #896) now covers crashes, but on purpose not a clean quit: its copy is removed when the app closes normally. One accidental Ctrl+Q therefore still loses the work. The automated review on #896 flagged this twice. ArcGIS Pro and QGIS ask before discarding unsaved changes.

Proposed solution

A "Save changes to Parcels?" dialog with Save, Don't Save and Cancel, shown by the desktop interface before an action would discard unsaved changes:

  • Quit and closing the window. Handle the viewport's close request: cancel it, ask, then close once the user has chosen Save (and the save succeeded) or Don't Save. Cmd+Q on macOS should take the same path; I'll verify it does.
  • Replacing the project: New, Open, the sample, a template, a recent project, a dropped project file, and Command Search's routes to those.
  • Save saves first, using Save As when the project has no file. If that is cancelled or fails, nothing is discarded. Don't Save goes ahead. Cancel goes back to the project.

Commands still never open dialogs. project.new, project.open and the rest keep working silently for the CLI, Python, scripts, the AI Assistant and MCP clients. The check sits at the interface's dispatch, so it covers keyboard shortcuts and the ribbon in one place, not one prompt per button. Calls from the AI Assistant and the relay stay unprompted. Whether the Assistant should also ask before replacing a project with unsaved changes is a separate question.

Unsaved means unsaved. Today undoing back to the saved state still counts as unsaved (Session::dirty is a single flag that undo doesn't clear), so the dialog would ask when nothing changed. The session would remember the undo position at the last save and treat the project as saved when undo or redo returns there. This also makes the title's "•" accurate.

With autosave. Don't Save removes the recovery copy, as a clean quit already does. A crash is unaffected.

Crates: rustgis-engine (the saved undo position), rustgis-ui-egui (the dialog and the dispatch check), apps/rustgis (the close request). No new dependency, no format or command changes.

Tests: headless UI tests that click through each choice for Quit, New and Open. They cover Save on a never-saved project (Save As cancelled keeps the project), a failed save (nothing discarded), and undo back to the saved state (no prompt). They also check that commands run directly don't prompt. Plus a ui_shot of the dialog.

I'm working on this. I'll start once #896 is merged, since both change the quit path.

Estimated scope

Medium: a broader feature that is feasible in a reasonable timeframe

Alternatives considered

  • Hot exit (VS Code-style): never ask, keep the recovery copy on quit and reopen the work at the next start. It reuses feat(ui): autosave unsaved work and offer it back after a crash #896, but the recovery dialog would then appear after ordinary quits, and it needs a final copy written at exit, not the last interval's. It could be an opt-in setting later.
  • A prompt in each command: this would break the rule that commands never open dialogs, and would stop scripts and agents.

Activity

  1. self-assigned this
    on Oct 25, 2026
  2. added a commit that references this issue on Oct 26, 2026
    aeaebc2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions