// Sync & Backup. // // Three answers to three different questions, which is why they sit together: // carrying settings to a different machine, putting this machine's settings // back as they were, and throwing them away. // // The backups here are copies of the preferences file. They are not the btrfs // snapshots one tab over in System › Snapshots, which put the whole filesystem // back -- the card says so, because the two used to share the word "Snapshots" // and nothing distinguished them. import QtQuick import qs.config import qs.services SettingsPage { id: root title: "Sync & Backup" lede: "Carry your settings to another machine, keep copies of them, or start over." // Distinct from the backups below, which put THIS machine back as it was. // This carries settings to a different one, and deliberately leaves behind // anything that describes hardware. SettingsCard { title: "Carry settings to another machine" subtitle: SettingsSync.lastError !== "" ? SettingsSync.lastError : "Everything except what describes this machine: the display arrangement stays here." ActionRow { label: "Export" detail: SettingsSync.lastAction === "export" && SettingsSync.carried > 0 ? SettingsSync.carried + " settings written to " + SettingsSync.defaultPath : "Writes " + SettingsSync.defaultPath action: "Export" enabled: !SettingsSync.busy onTriggered: SettingsSync.exportTo(SettingsSync.defaultPath) } ActionRow { label: "See what an import would change" detail: SettingsSync.previewed ? SettingsSync.changes.length + " would change, " + SettingsSync.skipped.length + " skipped" : "Reads " + SettingsSync.defaultPath + " without applying anything" action: "Preview" enabled: !SettingsSync.busy onTriggered: SettingsSync.preview(SettingsSync.defaultPath) } // Only offered once a preview has said what it would do. Importing // settings sight unseen is how somebody ends up wondering why their // desktop changed. ActionRow { visible: SettingsSync.previewed && SettingsSync.changes.length > 0 label: "Apply those " + SettingsSync.changes.length + " changes" detail: "Settings the file does not mention are left alone" action: "Import" enabled: !SettingsSync.busy onTriggered: SettingsSync.importFrom(SettingsSync.defaultPath) } Repeater { model: SettingsSync.previewed ? SettingsSync.skipped : [] delegate: TextRow { required property var modelData width: parent.width label: String(modelData.key ?? "") detail: "Skipped: " + String(modelData.reason ?? "") value: "" } } TextRow { visible: SettingsSync.lastAction === "import" && SettingsSync.lastError === "" label: SettingsSync.applied === 0 ? "Nothing needed changing" : SettingsSync.applied + " settings applied" detail: "From " + (SettingsSync.exportedFrom || "the export") value: "" divider: false } } SettingsCard { title: "Settings backups" subtitle: SettingsBackup.lastError !== "" ? SettingsBackup.lastError : "Copies of your preferences, not of the filesystem — System › Snapshots keeps the btrfs ones. Your whole desktop configuration is a single file, so a backup is a copy of it. Restoring also backs up what it replaces, so it is itself undoable." ActionRow { label: "Back up current settings" detail: SettingsBackup.snapshots.length === 0 ? "No backups yet" : SettingsBackup.snapshots.length + (SettingsBackup.snapshots.length === 1 ? " backup kept" : " backups kept") + ", newest first" action: "Back up now" enabled: !SettingsBackup.busy divider: SettingsBackup.snapshots.length > 0 onTriggered: SettingsBackup.save() } Repeater { id: snapshotRows model: SettingsBackup.snapshots ActionRow { required property var modelData required property int index label: modelData.when detail: modelData.keys + " settings" action: "Restore" enabled: !SettingsBackup.busy divider: index < snapshotRows.count - 1 onTriggered: SettingsBackup.restore(modelData.name) } } } SettingsCard { title: "Reset" subtitle: "Restores the appearance, dock, clock, focus, and display policy, and clears your Home accessory arrangement. Pinned applications, files, and paired devices are not changed." ActionRow { label: "Restore defaults" detail: "Applies immediately, including to the compositor" action: "Restore defaults" divider: false onTriggered: SystemSettings.restoreDefaults() } } }