anki/qt/aqt/forms
Damien Elmes 4515c41d2c
Backup improvements (#1728)
* Collection needs to be closed prior to backup even when not downgrading

* Backups -> BackupLimits

* Some improvements to backup_task

- backup_inner now returns the error instead of logging it, so that
the frontend can discover the issue when they await a backup (or create
another one)
- start_backup() was acquiring backup_task twice, and if another thread
started a backup between the two locks, the task could have been accidentally
overwritten without awaiting it

* Backups no longer require a collection close

- Instead of closing the collection, we ensure there is no active
transaction, and flush the WAL to disk. This means the undo history
is no longer lost on backup, which will be particularly useful if we
add a periodic backup in the future.
- Because a close is no longer required, backups are now achieved with
a separate command, instead of being included in CloseCollection().
- Full sync no longer requires an extra close+reopen step, and we now
wait for the backup to complete before proceeding.
- Create a backup before 'check db'

* Add File>Create Backup

https://forums.ankiweb.net/t/anki-mac-os-no-backup-on-sync/6157

* Defer checkpoint until we know we need it

When running periodic backups on a timer, we don't want to be fsync()ing
unnecessarily.

* Skip backup if modification time has not changed

We don't want the user leaving Anki open overnight, and coming back
to lots of identical backups.

* Periodic backups

Creates an automatic backup every 30 minutes if the collection has been
modified.

If there's a legacy checkpoint active, tries again 5 minutes later.

* Switch to a user-configurable backup duration

CreateBackup() now uses a simple force argument to determine whether
the user's limits should be respected or not, and only potentially
destructive ops (full download, check DB) override the user's configured
limit.

I considered having a separate limit for collection close and automatic
backups (eg keeping the previous 5 minute limit for collection close),
but that had two downsides:

- When the user closes their collection at the end of the day, they'd
get a recent backup. When they open the collection the next day, it
would get backed up again within 5 minutes, even though not much had
changed.
- Multiple limits are harder to communicate to users in the UI

Some remaining decisions I wasn't 100% sure about:

- If force is true but the collection has not been modified, the backup
will be skipped. If the user manually deleted their backups without
closing Anki, they wouldn't get a new one if the mtime hadn't changed.
- Force takes preference over the configured backup interval - should
we be ignored the user here, or take no backups at all?

Did a sneaky edit of the existing ftl string, as it hasn't been live
long.

* Move maybe_backup() into Collection

* Use a single method for manual and periodic backups

When manually creating a backup via the File menu, we no longer make
the user wait until the backup completes. As we continue waiting for
the backup in the background, if any errors occur, the user will get
notified about it fairly quickly.

* Show message to user if backup was skipped due to no changes

+ Don't incorrectly assert a backup will be created on force

* Add "automatic" to description

* Ensure we backup prior to importing colpkg if collection open

The backup doesn't happen when invoked from 'open backup' in the profile
screen, which matches Anki's previous behaviour. The user could
potentially clobber up to 30 minutes of their work if they exited to
the profile screen and restored a backup, but the alternative is we
create backups every time a backup is restored, which may happen a number
of times if the user is trying various ones. Or we could go back to a
separate throttle amount for this case, at the cost of more complexity.

* Remove the 0 special case on backup interval; minimum of 5 minutes

https://github.com/ankitects/anki/pull/1728#discussion_r830876833
2022-03-21 19:40:42 +10:00
..
__init__.py Optionally restore original position and reset counts when forgetting (#1714) 2022-03-09 16:51:41 +10:00
about_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
about.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
about.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
addcards_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
addcards.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
addcards.ui Remove unused actions from ui files (#1655) 2022-02-11 10:15:36 +10:00
addfield_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
addfield.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
addfield.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
addmodel_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
addmodel.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
addmodel.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
addonconf_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
addonconf.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
addonconf.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
addons_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
addons.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
addons.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
browser_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
browser.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
browser.ui View menu (#1668) 2022-02-17 16:31:46 +10:00
browserdisp_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
browserdisp.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
browserdisp.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
browseropts_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
browseropts.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
browseropts.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
build_ui_qt5.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
build_ui_qt6.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
build_ui.py remove a few unnecessary PyQt workarounds 2021-10-24 14:24:35 +10:00
BUILD.bazel improve PyQt install 2021-10-23 10:56:17 +10:00
changemap_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
changemap.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
changemap.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
changemodel_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
changemodel.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
changemodel.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
clayout_top_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
clayout_top.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
clayout_top.ui Increased max visible items from clayout_top.ui (#1425) 2021-10-14 19:36:04 +10:00
compile.bzl build all the UI files in one go 2021-10-16 09:20:20 +10:00
customstudy_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
customstudy.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
customstudy.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
dconf_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
dconf.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
dconf.ui split deck description into separate screen linked from overview 2021-04-22 21:03:16 +10:00
debug_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
debug.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
debug.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
editaddon_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
editaddon.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
editaddon.ui update designer references 2020-11-17 19:55:18 +10:00
editcurrent_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
editcurrent.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
editcurrent.ui update designer references 2020-11-17 19:55:18 +10:00
edithtml_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
edithtml.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
edithtml.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
emptycards_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
emptycards.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
emptycards.ui update designer references 2020-11-17 19:55:18 +10:00
exporting_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
exporting.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
exporting.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
fields_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
fields_web_qt6.py Add a flag to allow loading the fields dialog in a web view (#1706) 2022-03-03 22:45:26 +10:00
fields_web.py Add a flag to allow loading the fields dialog in a web view (#1706) 2022-03-03 22:45:26 +10:00
fields_web.ui Add a flag to allow loading the fields dialog in a web view (#1706) 2022-03-03 22:45:26 +10:00
fields.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
fields.ui Editor Field Descriptions (#1476) 2021-11-06 09:42:48 +10:00
filtered_deck_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
filtered_deck.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
filtered_deck.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
finddupes_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
finddupes.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
finddupes.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
findreplace_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
findreplace.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
findreplace.ui switch to new-style PyQt scoped enums and Qt6 2021-10-15 12:57:19 +10:00
forget_qt6.py Optionally restore original position and reset counts when forgetting (#1714) 2022-03-09 16:51:41 +10:00
forget.py Optionally restore original position and reset counts when forgetting (#1714) 2022-03-09 16:51:41 +10:00
forget.ui Optionally restore original position and reset counts when forgetting (#1714) 2022-03-09 16:51:41 +10:00
getaddons_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
getaddons.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
getaddons.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
icons.qrc fix generated code symlinks again 2022-01-24 16:59:37 +10:00
importing_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
importing.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
importing.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
main_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
main.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
main.ui Backup improvements (#1728) 2022-03-21 19:40:42 +10:00
modelopts_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
modelopts.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
modelopts.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
models_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
models.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
models.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
preferences_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
preferences.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
preferences.ui Backup improvements (#1728) 2022-03-21 19:40:42 +10:00
preview_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
preview.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
preview.ui initial Bazel conversion 2020-11-01 14:26:58 +10:00
profiles_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
profiles.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
profiles.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
progress_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
progress.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
progress.ui update designer references 2020-11-17 19:55:18 +10:00
reposition_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
reposition.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
reposition.ui require reposition to start at 0; cap maximum 2021-06-01 10:09:24 +10:00
setgroup_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
setgroup.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
setgroup.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
setlang_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
setlang.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
setlang.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
stats_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
stats.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
stats.ui update designer references 2020-11-17 19:55:18 +10:00
studydeck_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
studydeck.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
studydeck.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
synclog_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
synclog.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
synclog.ui initial Bazel conversion 2020-11-01 14:26:58 +10:00
taglimit_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
taglimit.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
taglimit.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00
template_qt6.py fix generated code symlinks again 2022-01-24 16:59:37 +10:00
template.py generate pyqt6 forms 2021-10-15 12:57:19 +10:00
template.ui update TR references in .ui files 2021-03-26 15:03:51 +10:00