Commit Graph

3000 Commits

Author SHA1 Message Date
Damien Elmes
192dfe8185 Get the runtime Qt version instead of the compile-time version
PyQt sometimes bumps the Qt libraries without changing the Python side
2022-09-21 12:21:10 +10:00
Matthias Metelka
bff76727fe
Make mdi icons for Qt themeable (#2078)
* Fix create_vars_from_map not creating vars with default definition

* Add white and black to vars

* Replace some hard-coded SVGs with mdi equivalents

* Implement function to dynamically adjust SVG icon color

* Use new svg function to make Qt stylesheet icons respond to theme changes

* Use svg function for sidebar tool icons

* Create copy for each new color instead of modifying source file

* Fix check fails

* Add custom checkbox style for #2079

* Add example of how to generate svgs during build (dae)

* Create arbitrary color variants for each icon with Bazel

* Remove unused label (dae)
2022-09-21 12:02:30 +10:00
Matthias Metelka
e109c62aa9
Improve hover feedback on various widgets (#2079)
* Use cursor: pointer on QCheckBoxes too and exclude disabled widgets

* Left-align all QCheckBoxes to make hover-area and clickable area the same

Altough the clickable area has always been restricted to the label, the widget itself stretched all the way. This became a problem with the new cursor-pointer for checkboxes.

* Remove Switch duplicate from deck-options

* Add cursor: pointer to Switch and RevertButton

* Add cursor: pointer to bottom toolbar buttons

* Add cursor: pointer to gears

* Add cursor: pointer to radio and checkbox inputs of graphs page

* Improve button appearance in stats screen

* Add cursor: pointer to QTabBar and QToolButton

* Add cursor: pointer to non-editable QComboBox

* Center settings-will-take-effect-after notice in preferences screen

* Use public without_qt5_compat_wrapper() function

* Run prettier
2022-09-20 16:34:15 +10:00
Matthias Metelka
52f52724fa
Add orientation toggle to browser view menu (#2074)
* Use horizontal orientation on browser splitter by default

* Add View menu action to toggle browser orientation

* Add shortcut for toggleOrientation action

based on the most popular add-on.

* Try to fix typing issue

* Make orientation respond to aspect ratio

aspect ratio < 1 means vertical orientation, >= 1 horizontal

* Implement three-way switch for browser orientation

* Fix typing

* Add separator before QWidgetAction

* Use submenu instead of widget and adjust enum

* Add accelerators; move non-accelerator strings into separate .ftl (dae)

* Move BrowserLayout to its own file (dae)
2022-09-20 12:56:59 +10:00
Matthias Metelka
24abb06cee
Color Palette Patch 1 (#2073)
* Make several colors more faint

* Move selection-color definition out of table.py and adjust colors

* Use functions for repetitive border-gradient definitions

* Tweak QTableView and QScrollBar styles

* Use mdi icon for Qt drag handles and adjust padding in browser.ui

* Apply appropriate drag-handle icon depending on orientation

* Fix formatting

* Remove unused import

* Add right margin to browser layout

* Apply splitter styling on macOS as well (dae)

+ Remove the styling from sliders, as it was presumably not intentional.
2022-09-19 10:58:05 +10:00
Damien Elmes
5bf031f1e3 Fix reviewer shortcuts being inaccessible due to IME
Only tested on Windows, but hopefully resolves the Linux issue as well.

Closes #1952
2022-09-17 14:15:07 +10:00
Damien Elmes
39d59caa48 Possible fix for error when copying text in editor
https://forums.ankiweb.net/t/error-copying-data-when-editing-a-note-field-anki-2-1-54/23147
https://forums.ankiweb.net/t/error-during-performing-an-ahk-script/23070
2022-09-17 11:47:41 +10:00
Matthias Metelka
8142176f84
Introduce new color palette using Sass maps (#2016)
* Remove --medium-border variable

* Implement color palette using Sass maps

I hand-picked the gray tones, the other colors are from the Tailwind CSS v3 palette.

Significant changes:
- light theme is brighter
- dark theme is darker
- borders are softer

I also deleted some platform- and night-mode-specific code.

* Use custom colors for note view switch

* Use same placeholder color for all inputs

* Skew color palette for more dark values

by removing gray[3], which wasn't used anywhere. Slight adjustments were made to the darker tones.

* Adjust frame- window- and border colors

* Give deck browser entries --frame-bg as background color

* Define styling for QComboBox and QLineEdit globally

* Experiment with CSS filter for inline-colors

Inside darker inputs, some colors like dark blue will be hard to read, so we could try to improve text-color contrast with global adjustments depending on the theme.

* Use different map structure for _vars.scss

after @hgiesel's idea: https://github.com/ankitects/anki/pull/2016#discussion_r947087871

* Move custom QLineEdit styles out of searchbar.py

* Merge branch 'main' into color-palette

* Revert QComboBox stylesheet override

* Align gray color palette more with macOS

* Adjust light theme

* Use --slightly-grey-text for options tab color

* Replace gray tones with more neutral values

* Improve categorization of global colors

by renaming almost all of them and sorting them into separate maps.

* Saturate highlight-bg in light theme

* Tweak gray tones

* Adjust box-shadow of EditingArea to make fields look inset

* Add Sass functions to access color palette and semantic variables

in response to https://github.com/ankitects/anki/pull/2016#issuecomment-1220571076

* Showcase use of access functions in several locations

@hgiesel in buttons.scss I access the color palette directly. Is this what you meant by "... keep it local to the component, and possibly make it global at a later time ..."?

* Fix focus box shadow transition and remove default shadow for a cleaner look

I couldn't quite get the inset look the way I wanted, because inset box-shadows do not respect the border radius, therefore causing aliasing.

* Tweak light theme border and shadow colors

* Add functions and colors to base_lib

* Add vars_lib as dependency to base_lib and button_mixins_lib

* Improve uses of default-themed variables

* Use old --frame-bg color and use darker tone for canvas-default

* Return CSS var by default and add palette-of function for raw value

* Showcase use of palette-of function

The #{...} syntax is required only because the use cases are CSS var definitions. In other cases a simple palette-of(keyword, theme) would suffice.

* Light theme: decrease brightness of canvas-default and adjust fg-default

* Use canvas-inset variable for switch knob

* Adjust light theme

* Add back box-shadow to EditingArea

* Light theme: darken background and flatten transition

also set hue and saturation of gray-8 to 0 (like all the other grays).

* Reduce flag colors to single default value

* Tweak card/note accent colors

* Experiment with inset look for fields again

Is this too dark in night mode? It's the same color used for all other text inputs.

* Dark theme: make border-default one shade darker

* Tweak inset shadow color

* Dark theme: make border-faint darker than canvas-default

meaning two shades darker than it currently was.

* Fix PlainTextInput not expanding

* Dark theme: use less saturated flag colors

* Adjust gray tones

* Fix nested variables not getting extracted correctly

* Rename canvas-outset to canvas-elevated

* Light theme: darken canvas-default

* Make canvas-elevated a bit darker

* Rename variables and use them in various components

* Refactor button mixins

* Remove fusion vars from Anki

* Adjust button gradients

* Refactor button mixins

* Fix deck browser table td background color

* Use color function in buttons.scss

* Rework QTabWidget stylesheet

* Fix crash on browser open

* Perfect QTableView header

* Fix bottom toolbar button gradient

* Fix focus outline of bottom toolbar buttons

* Fix custom webview scrollbar

* Fix uses of vars in various webviews

The command @use vars as * lead to repeated inclusion of the CSS vars.

* Enable primary button color with mixin

* Run prettier

* Fix Python code style issues

* Tweak colors

* Lighten scrollbar shades in light theme

* Fix code style issues caused by merge

* Fix harsh border color in editor

caused by leftover --medium-border variables, probably introduced with a merge commit.

* Compile Sass before extracting Python colors/props

This means the Python side doesn't need to worry about the map structure and Sass functions, just copy the output CSS values.

* Desaturate primary button colors by 10%

* Convert accidentally capitalized variable names to lowercase

* Simplify color definitions with qcolor function

* Remove default border-focus variable

* Remove redundant colon

* Apply custom scrollbar CSS only on Windows and Linux

* Make border-subtle color brighter than background in dark theme

* Make border-subtle color a shade brighter in light theme

* Use border-subtle for NoteEditor and EditorToolbar border

* Small patches
2022-09-16 14:11:18 +10:00
Zoom
3ec7e23d7c
Fix Windows dark mode detection: OpenKey can fail (#2068)
* Fix Windows dark mode detection: OpenKey can fail

#1497 introduced reading hardcoded Windows Registry key, which assumes key exists. This is not true on Windows 7. Later addition of `try-except` block missed that OpenKey might fail.

This fix allows launching current version of Anki on Windows 7 when installed with Pip with the modified Python 3.9 installation.

* Update CONTRIBUTORS

CI req: Add myself to the contributor list
2022-09-15 12:04:19 +10:00
Abdo
497b246b66
Add MainWindowState hints to more signatures (#2064) 2022-09-12 19:31:22 +10:00
Henrik Giesel
8f8f3bd465
Insert symbols overlay (#2051)
* Add flag for enabling insert symbols feature

* Add symbols overlay directory

* Detect if :xy is inserted into editable

* Allow naive updating of overlay, and special handling of ':'

* First step towards better Virtual Element support

* Update floating to reference range on insert text

* Position SymbolsOverlay always on top or bottom

* Add a data-provider to emulate API

* Show correct suggestions in symbols overlay

* Rename to replacementLength

* Allow replacing via clicking in menu

* Optionally remove inline padding of Popover

* Hide Symbols overlay on blur of content editable

* Add specialKey to inputHandler and generalize how arrow movement is detected

- This way macOS users can use Ctrl-N to mean down, etc.

* Detect special key from within SymbolsOverlay

* Implement full backwards search while typing

* Allow navigating symbol menu and accepting with enter

* Add some entries to data-provider

* Satisfy eslint

* Generate symbolsTable from sources

* Use other github source, allow multiple names

In return, symbol must be unique

* Automatically scroll in symbols dropdown

* Use from npm packages rather than downloading from URL

* Remove console.log

* Remove print

* Add pointerDown event to input-handler

- so that SymbolsOverlay can reset on field click

* Make tab do the same as enter

* Make font a bit smaller but increase relative icon size

* Satisfy type requirement of handlerlist

* Revert changing default size of DropdownItems

* Remove some now unused code for bootstrap dropdowns
2022-09-10 18:46:59 +10:00
Matthias Metelka
414ff5db1c
Redesign Qt widgets with stylesheets (#2050)
* Remove --medium-border variable

* Implement color palette using Sass maps

I hand-picked the gray tones, the other colors are from the Tailwind CSS v3 palette.

Significant changes:
- light theme is brighter
- dark theme is darker
- borders are softer

I also deleted some platform- and night-mode-specific code.

* Use custom colors for note view switch

* Use same placeholder color for all inputs

* Skew color palette for more dark values

by removing gray[3], which wasn't used anywhere. Slight adjustments were made to the darker tones.

* Adjust frame- window- and border colors

* Give deck browser entries --frame-bg as background color

* Define styling for QComboBox and QLineEdit globally

* Experiment with CSS filter for inline-colors

Inside darker inputs, some colors like dark blue will be hard to read, so we could try to improve text-color contrast with global adjustments depending on the theme.

* Use different map structure for _vars.scss

after @hgiesel's idea: https://github.com/ankitects/anki/pull/2016#discussion_r947087871

* Move custom QLineEdit styles out of searchbar.py

* Merge branch 'main' into color-palette

* Revert QComboBox stylesheet override

* Align gray color palette more with macOS

* Adjust light theme

* Add custom styling for Qt controls

* Use --slightly-grey-text for options tab color

* Replace gray tones with more neutral values

* Improve categorization of global colors

by renaming almost all of them and sorting them into separate maps.

* Saturate highlight-bg in light theme

* Tweak gray tones

* Adjust box-shadow of EditingArea to make fields look inset

* Add Sass functions to access color palette and semantic variables

in response to https://github.com/ankitects/anki/pull/2016#issuecomment-1220571076

* Showcase use of access functions in several locations

@hgiesel in buttons.scss I access the color palette directly. Is this what you meant by "... keep it local to the component, and possibly make it global at a later time ..."?

* Fix focus box shadow transition and remove default shadow for a cleaner look

I couldn't quite get the inset look the way I wanted, because inset box-shadows do not respect the border radius, therefore causing aliasing.

* Tweak light theme border and shadow colors

* Add functions and colors to base_lib

* Add vars_lib as dependency to base_lib and button_mixins_lib

* Improve uses of default-themed variables

* Use old --frame-bg color and use darker tone for canvas-default

* Return CSS var by default and add palette-of function for raw value

* Showcase use of palette-of function

The #{...} syntax is required only because the use cases are CSS var definitions. In other cases a simple palette-of(keyword, theme) would suffice.

* Light theme: decrease brightness of canvas-default and adjust fg-default

* Use canvas-inset variable for switch knob

* Adjust light theme

* Add back box-shadow to EditingArea

* Light theme: darken background and flatten transition

also set hue and saturation of gray-8 to 0 (like all the other grays).

* Reduce flag colors to single default value

* Tweak card/note accent colors

* Experiment with inset look for fields again

Is this too dark in night mode? It's the same color used for all other text inputs.

* Dark theme: make border-default one shade darker

* Tweak inset shadow color

* Dark theme: make border-faint darker than canvas-default

meaning two shades darker than it currently was.

* Fix PlainTextInput not expanding

* Dark theme: use less saturated flag colors

* Adjust gray tones

* Create stylesheet overrides for various Qt widgets

Including QPushButton, QComboBox, QSpinBox, QLineEdit, QListWidget, QTabWidget, QTreeWidget, QToolTip, QTableView, QScrollBar and sub-widgets.

* Make webview scrollbar look identical to Qt one

* Add blue colors for primary buttons

* Tweak disabled state of SpinBox button

* Apply styles to all platforms

mainly so people like @hgiesel can easily test the widget style overrides, but maybe you actually prefer them over the native ones, who knows :)

* Tweak webview button borders

* Add type annotations to eventFilter

* Adjust padding of QComboBox and its drop-down arrow

* Use isinstance for comparison

* Remove reimport of Any

* Revert "Merge branch 'redesign-test' into custom-qt-controls"

This reverts commit ff36297456b693a0d4b4b69f5f487ac1a01c1861, reversing
changes made to 6bb45355d143aa081d2d643933bd02ddc43206de.

* Add missing copyright header

* Left-align QTabWidget headers

* Exclude macOS from stylesheet overrides

* Fix failure to start on macOS (dae)

* Use standard macOS theme in dark mode (dae)

I believe this was originally behind a feature flag because the user
had to use a hack to get it to work
(https://forums.ankiweb.net/t/title-bar-dark-mode-fix-broken/1189),
and it did not work correctly when the system theme was changed.

Since the introduction of libankihelper and the app automatically
updating as the system theme changes, these issues no longer seem to
exist, and switching between light and dark appears to work consistently.

Pushed into this PR because it addresses the background color issue
mentioned in code review.

Closes #2054
2022-09-08 20:44:38 +10:00
RumovZ
e7af0febb1
More template checks (#2032)
* Show warning if multiple type boxes are used

* Report templates referencing media in Media Check

* Apply suggestions from code review

* Fix media-check.ftl

* Only report media references with fields

Like `<img src={{Front}}>`.
Also report Anki sound tags and latex.

* Loop existing media regexes
2022-09-05 16:52:25 +10:00
RumovZ
e39fb74e82
Enable state-dependent custom scheduling data (#2049)
* Enable state-dependent custom scheduling data

* Next(Card)States -> SchedulingStates

The fact that `current` was included in `next` always bothered me,
and custom data is part of the card state, so that was a bit confusing
too.

* Store custom_data in SchedulingState

* Make custom_data optional when answering

Avoids having to send it 4 extra times to the frontend, and avoids the
legacy answerCard() API clobbering the stored data.

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2022-09-05 16:48:01 +10:00
Matthias Metelka
e2193950a9
Add animation toggle to preferences (#2041)
* Add animation toggle to preferences

and move settings affecting appearance together.

* Add class to body if animations unchecked

* Fix formatting in preferences.ftl

* Update duration(height) function for Collapsible transition

and add explanation.

* Fix formatting

* Increase duration baseline to 10 and decrease factor to 20

* Restore initial layout and rename option to "Reduce motion"

* Move checkboxes together and fix tab order (dae)

+ Remove separation of UI size
2022-09-03 12:14:47 +10:00
RumovZ
31b7464c67
Add card meta for persisting custom scheduling state (#2040)
* Add card meta for persisting custom scheduling state

* Rename meta -> custom_data

* Enforce limits on size of custom data

Large values will slow down table scans of the cards table, and it's
easier to be strict now and possibly relax things in the future than
the opposite.

* Pack card states and customData into a single message

+ default customData to empty if it can't be parsed

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2022-09-02 11:22:49 +10:00
Matthias Metelka
d110c4916c
Introduce setting to collapse field by default (#1990)
* Introduce setting to collapse field by default

* Fix schema order

* Change wording from adjective to imperative

sounds a bit less clunky

* Update rslib/src/notetype/schema11.rs (dae)

* Keep settings in single column

* Add back Toggle Visual Editor string

* Add RichTextBadge component and show it conditionally

* Reverse input order depending on default setting

* Make PlainTextInput border-radius responsive to toggle states

* Prevent first Collapsible transition differently

* Focus inputs after Collapsible transition

The double tick calls are just a temporary solution until I find the exact moment an input is focusable again.

* Use requestAnimationFrame to await focusable state

Note: Svelte tick doesn't seem to work in this scenario.
2022-08-31 23:34:39 +10:00
Sam Penny
65601196ee
add shortcut to close addcards window (#2031) 2022-08-31 20:09:09 +10:00
wallgrenen
0eaa80dd28
change update link to point to download section (#2034) 2022-08-31 18:35:53 +10:00
Damien Elmes
966d7f3760 Experimentally remove webview recycling
It was originally introduced for WebKit, and may no longer be pertinent
for Chromium.WebEngine.

https://forums.ankiweb.net/t/anki-glitch-showing-previous-card-answer-instead-of-new-card/12482/13
2022-08-30 21:52:22 +10:00
Damien Elmes
89c4441837 Fix scheduler change not reflected after normal sync 2022-08-24 18:37:58 +10:00
Sam Penny
45f2502e5b
fix line break in sync link in the toolbar (#2022) 2022-08-22 11:26:57 +10:00
Damien Elmes
fc93ea3ecc Show a pop-up when the user tries to study with V1
Closes #1991
2022-08-19 12:43:17 +10:00
Sam Bradshaw
92171e25e6
Add MessageBox class and associated funcs to aqt.utils and update the first few callers (#2010)
* Add MessageBox class and associated funcs to aqt.utils and update some callers in aqt.sync and aqt.addons

* Cleanup imports in aqt.sync

* Fix return values for ask_user and ask_user_dialog

* Fix wrong argument name in aqt.utils.ask_user

* Add type annotations to **kwargs in utils.py

* Type annotation for callback in aqt.sync.full_sync

* MessageBox accepts StandardButton in addition to str, fix linting issues

* Assess default buttons in correct order and return correct button name in MessageBox

* Add explicit Optionals in aqt.utils

* Pass button index to callback in MessageBox

* Update type hints for aqt.utils.MessageBox

* Use Sequence for aqt.utils.MessageBox buttons arg

* default_button > default_yes in aqt.utils.ask_user

* Dark mode question icon  in aqt.utils.MessageBox
2022-08-19 10:04:58 +10:00
Damien Elmes
19deb7ad25 Access certificates periodically
Tentatively closes #1965
2022-08-19 10:00:38 +10:00
Matthias Metelka
7517af4942
Fix not being able to scroll when mouse hovers PlainTextInput (#2019)
* Remove overscroll-behavior: none for * (all elements)

* Revert "Remove overscroll-behavior: none for * (all elements)"

This reverts commit 189358908cecd03027e19d8fe47822735319ec17.

* Use body instead of *, but keep CSS rule

* Unify two CSS rules
2022-08-18 12:48:28 +10:00
Matthias Metelka
d1cbb86178
Default input setting in fields dialog (#1987)
* Introduce field setting to use plain text editor by default

* Remove leftover function from #1476

* Use boolean instead of string

* Simplify clear_other_field_duplicates

* Convert plain text key to camelCase

* Move HTML item below the existing checkbox, instead of to the right (dae)

Showing it on the right is more space efficient, but feels a bit
cluttered IMHO.
2022-08-18 12:30:18 +10:00
Damien Elmes
75723d7c9c
Add option in math dropdown to toggle MathJax rendering (#2014)
* Add option in math dropdown to toggle MathJax rendering

Closes #1942

* Hackily redraw the page when toggling MathJax

* Add Fluent string
2022-08-18 12:06:06 +10:00
Matthias Metelka
d5945a213a
Make sidebar search input more pleasant to look at (#2009)
* Improve margins

* Remove right border on non-macOS systems

Would be interesting to know why this was implemented in the first place. Looks quite ugly on Linux.

* Add focus border

* Align height of toolbar icons with search bar

* Remove leftover f-strings
2022-08-15 13:08:44 +10:00
Matthias Metelka
99f4f68aca
Make switch knob smaller than path (#2008)
to ensure contrast when we move to a lighter window-bg color.
2022-08-15 13:05:20 +10:00
Sam Penny
21812556a6
Serialize modal popups at startup (#2000)
* call_add-on_update_after_initial_sync

* Add safeMode restriction

* check for anki update after other modal dialogs

* fix failing test

* make changes suggested in review
2022-08-09 13:40:52 +10:00
Sam Bradshaw
c4d71eae2f
Use platform.platform() in supportText() (#1999)
From [the documentation](https://docs.python.org/3.9/library/platform.html#platform.platform):
> Returns a single string identifying the underlying platform with as much useful information as possible.
The output is intended to be human readable rather than machine parseable. It may look different on different platforms and this is intended.
Changed in version 3.8: On macOS, the function now uses mac_ver(), if it returns a non-empty release string, to get the macOS version rather than the darwin version.

The main advantage of this change is that it provides the architecture of the platform, which is increasingly relevant as ARM systems are becoming more common.
2022-08-02 19:49:02 +10:00
BlueGreenMagick
a7208601fe
fix progress.update(value=0) to not increment progress (#1998) 2022-08-01 20:16:42 +10:00
Henrik Giesel
3e28605638
Use wavy flags (flag-alternative) (#1995) 2022-08-01 20:15:22 +10:00
Damien Elmes
8a62e9c95e Ensure only the first fatal error is shown
https://forums.ankiweb.net/t/a-fatal-error-occurred-and-anki-must-close-please-report-this-message-on-the-forums/21913
2022-08-01 19:38:46 +10:00
Sam Penny
56f806146c
added editor hook: add_cards_might_add_note (#1992)
* added hook add_cards_might_add_note

* fix failing test
2022-07-30 20:41:42 +10:00
Damien Elmes
d699bc1252 Handle missing attributes in win32 tts code
https://forums.ankiweb.net/t/trouble-adding-tts-to-my-cards/21792/4
2022-07-30 19:08:37 +10:00
Hikaru Y
e6cc12ca7a
Fix sidebar not being restored properly in some cases (#1982)
The sidebar (QDockWidget) was not restored properly in some environments
when re-opening the browser if the browser was closed while maximized
under the condition that the window size in the normal window state was
very small.
2022-07-23 16:12:02 +10:00
Damien Elmes
340da23104 Wrap type answer output in code tag; remove extra div
This would make more sense as a class on the outer div, but existing
templates reference code#typeans, so avoid breaking things for now.
2022-07-22 20:37:56 +10:00
Aristotelis
a584ef1f50
Introduce exporters_list_created hook to new export code (#1978)
* Introduce exporters_list_created hook for new export code

* Fix hook and argument name
2022-07-22 19:33:07 +10:00
Damien Elmes
1e0be26b7e Partially migrate type answer to backend
Partially completes #1068, and will allow mobile clients to drop
their separate diff-match-patch imports. Does not yet try to handle
case folding or combining-char stripping, and leaves some of the outer
HTML wrapping up to the frontend for now.

The logic for rendering the provided string has changed: missing chars
are now only inserted if they follow a correct section, and the original
text is shown instead of hyphens. This is an experiment, and can be
changed if it's not well received.
2022-07-22 19:28:34 +10:00
Aristotelis
070c8ac735
Add deck/collection export hooks (#1971)
* Add ExportFormat enum and use it in Exporter classes

* Add exporter hooks and call them from new exporters

* Fix filter argument order and add example to docstring

* Refactor: Avoid repeating ExportFormat

* Rename Options to ExportOptions for better namespacing in add-ons

* Add simplified legacy exporter hooks

Allows add-ons to be notified of exports when legacy handlers are enabled, without the need for monkey-patches.

* Switch away from ExportFormat, opting to pass exporter class/instance instead

* Consistently use exporter instances rather than classes

* Revert Exportdialog.exporters rename

* Revert "Revert Exportdialog.exporters rename"

This reverts commit 357a3aa85928cce702f06b88da5187d2b45cd22b.
2022-07-22 12:45:47 +10:00
Sam Penny
e0368a3858
modify type hint in aqt/qt/profiles (#1972) 2022-07-19 17:29:46 +10:00
Aristotelis
704ff7ab99
Fix legacy import switch (#1970) 2022-07-19 04:23:21 +10:00
Damien Elmes
d482e90c6b Turn new import/export code on by default
Closes #1966
2022-07-18 13:31:24 +10:00
Sam Penny
662586765b
Load previously loaded profile (#1960)
* added option to load the last loaded profile

* add formatting changes for tests

* fix comments - integrate as new functionality rather than as an option, fix type hinting and remove bug if profile is deleted
2022-07-18 13:01:36 +10:00
Mateus Etto
d7d9f51b68
Add reviewer suspend and bury hooks (#1967)
* Add reviewer suspend and bury hooks

* Empty commit

* Change my name in CONTRIBUTORS
2022-07-18 12:59:56 +10:00
Damien Elmes
2625388e8d Ensure files are world readable in macOS dist
Closes #1934
2022-07-12 13:04:48 +10:00
RumovZ
cff04a288a
Fix card info not updating (#1957)
Update was not triggered if card id didn't change.
2022-07-12 10:34:48 +10:00
Damien Elmes
ca69198097 Tweak type-answer example so users don't think the spelling is a mistake
https://github.com/ankitects/anki/pull/1954
2022-07-09 12:24:43 +10:00
Sam Penny
9dcceff4af
Remember previous choices in reposition dialog (#1950)
* remember previous choices in reposition dialog

* remember previous choice for randomize option as well

* fix failing test
2022-07-08 11:28:38 +10:00
Mateus Etto
fbbd3e678c
Add hook: overview_will_render_bottom (#1946) 2022-07-05 08:28:47 +10:00
Abdo
fe302a5d1b
Use portable filter to match all files in getFile (#1943)
`*.*` matches files with no extensions on Windows, while it doesn't do so on
macOS.

Reference: https://doc.qt.io/qt-6/qfiledialog.html#setNameFilters
2022-07-04 09:33:20 +10:00
Sam Penny
1e8ea0cade
fixed hook description (browser_will_search) (#1937)
* fixed hook description

* added name to CONTRIBUTORS
2022-07-01 10:12:27 +10:00
Mateus Etto
af8ae69837
Fix Study Deck in Sway spawning tiled window instead of floating window (#1935)
* Fix Study Deck in sway spawning tiled window instead of floating window

* Update CONTRIBUTORS

* Fix format error
2022-06-27 17:27:56 +10:00
RumovZ
dd0e56afb3
Handle note without cards in browser (#1929)
Change the IndexError to a NotFoundError which is picked up by the table
model.
2022-06-24 13:57:42 +10:00
RumovZ
cd3f9ff646
Workaround broken alignment flags in PyQt 6.3.1 (#1922)
Closes #1921
2022-06-22 09:44:50 +10:00
Damien Elmes
05adb50153 Prevent error when double-tapping delete key in browser
on_all_or_selected_rows_changed() unsets the editor note, but it is
called too late - by that time the note has already been deleted, and
the editor sometimes tries to save the deleted note due to an unfocus/
key timeout.

https://forums.ankiweb.net/t/two-suppr-lead-to-an-empty-warning/20860

Will need to check that this does not regression when #1691 is merged.
2022-06-20 11:07:38 +10:00
Damien Elmes
e5a74838c9 Remove redundant suffix in header key
We're already appending "Qt6"
2022-06-20 10:26:42 +10:00
Damien Elmes
32b9d34749 Add ellipsis to Forget action
https://forums.ankiweb.net/t/bug-card-browser-rmb-forget-label-should-end-with-ellipsis-because-it-displays-a-dialog/20851
2022-06-20 10:25:50 +10:00
Damien Elmes
48c7bb031e Work around broken headers in Qt 6.3.1
https://forums.ankiweb.net/t/anki-2-1-54-release-candidate/20861/2
2022-06-19 10:44:10 +10:00
Damien Elmes
595c92730f Remove CF_HTML header workaround 2022-06-18 09:56:06 +10:00
Abdo
67f64740c4
Accept .zip as an alias for .ankiaddon too (#1914) 2022-06-17 11:10:29 +10:00
Abdo
1bab947c9c
Fix JS drop event not firing in the reviewer (#1906)
* Allow webviews to opt in to default D&D handling

* Remove redundant webview.js include

* Block default drag & drop behavior in reviewing screens

* Fix mypy error
2022-06-10 23:33:53 +10:00
Damien Elmes
940f1dea06 Clear cached flag names on sync
Closes #1907
2022-06-09 12:08:16 +10:00
RumovZ
3816020085
Add legacy importers to new import screen (#1908) 2022-06-09 10:57:29 +10:00
RumovZ
6da5e5b042
CSV import/export fixes and features (#1898)
* Fix footer moving upwards

* Fix column detection

Was broken because escaped line breaks were not considered.
Also removes delimiter detection on `#columns:` line. User must use tabs
or set delimiter beforehand.

* Add CSV preview

* Parse `#tags column:`

* Optionally export deck and notetype with CSV

* Avoid clones in CSV export

* Prevent bottom of page appearing under footer (dae)

* Increase padding to 1em (dae)

With 0.5em, when a vertical scrollbar is shown, it sits right next to
the right edge of the content, making it look like there's no right
margin.

* Experimental changes to make table fit+scroll (dae)

- limit individual cells to 15em, and show ellipses when truncated
- limit total table width to body width, so that inner table is shown
with scrollbar
- use class rather than id - ids are bad practice in Svelte components,
as more than one may be displayed on a single page

* Skip importing foreign notes with filtered decks

Were implicitly imported into the default deck before.
Also some refactoring to fetch deck ids and names beforehand.

* Hide spacer below hidden field mapping

* Fix guid being replaced when updating note

* Fix dupe identity check

Canonify tags before checking if dupe is identical, but only add update
tags later if appropriate.

* Fix deck export for notes with missing card 1

* Fix note lines starting with `#`

csv crate doesn't support escaping a leading comment char. :(

* Support import/export of guids

* Strip HTML from preview rows

* Fix initially set deck if current is filtered

* Make isHtml toggle reactive

* Fix `html_to_text_line()` stripping sound names

* Tweak export option labels

* Switch to patched rust-csv fork

Fixes writing lines starting with `#`, so revert 5ece10ad05f331.

* List column options with first column field

* Fix flag for exports with HTML stripped
2022-06-09 10:28:01 +10:00
Bart Louwers
d6b8520d03
Update get_linux_dark_mode to use freedesktop.org standard (#1905)
* update get_linux_dark_mode to use freedesktop.org standard

* Update CONTRIBUTORS

* run formatter

* Update CONTRIBUTORS

* allow for multiple dark mode detection strategies on Linux

* string -> str

* update docstring

* Update CONTRIBUTORS
2022-06-07 09:30:42 +10:00
Damien Elmes
311d0342a0 Update regex in qt/bundle as well 2022-06-07 08:50:10 +10:00
Damien Elmes
a9884a1b78 Fix kwin hanging when adding new notetype
https://forums.ankiweb.net/t/bug-anki-2-1-52-crashes-after-adding-new-note-type/20284
2022-06-03 11:23:41 +10:00
Damien Elmes
9e5fef00d8 Expose new import/export code via prefs checkbox 2022-06-02 16:50:32 +10:00
RumovZ
42cbe42f06
Plaintext import/export (#1850)
* Add crate csv

* Add start of csv importing on backend

* Add Menomosyne serializer

* Add csv and json importing on backend

* Add plaintext importing on frontend

* Add csv metadata extraction on backend

* Add csv importing with GUI

* Fix missing dfa file in build

Added compile_data_attr, then re-ran cargo/update.py.

* Don't use doubly buffered reader in csv

* Escape HTML entities if CSV is not HTML

Also use name 'is_html' consistently.

* Use decimal number as foreign ease (like '2.5')

* ForeignCard.ivl → ForeignCard.interval

* Only allow fixed set of CSV delimiters

* Map timestamp of ForeignCard to native due time

* Don't trim CSV records

* Document use of empty strings for defaults

* Avoid creating CardGenContexts for every note

This requires CardGenContext to be generic, so it works both with an
owned and borrowed notetype.

* Show all accepted file types  in import file picker

* Add import_json_file()

* factor → ease_factor

* delimter_from_value → delimiter_from_value

* Map columns to fields, not the other way around

* Fallback to current config for csv metadata

* Add start of new import csv screen

* Temporary fix for compilation issue on Linux/Mac

* Disable jest bazel action for import-csv

Jest fails with an error code if no tests are available, but this would
not be noticable on Windows as Jest is not run there.

* Fix field mapping issue

* Revert "Temporary fix for compilation issue on Linux/Mac"

This reverts commit 21f8a261408cdae49ec031aa21a1b659c4f66d82.

* Add HtmlSwitch and move Switch to components

* Fix spacing and make selectors consistent

* Fix shortcut tooltip

* Place import button at the top with path

* Fix meta column indices

* Remove NotetypeForString

* Fix queue and type of foreign cards

* Support different dupe resolution strategies

* Allow dupe resolution selection when importing CSV

* Test import of unnormalized text

Close  #1863.

* Fix logging of foreign notes

* Implement CSV exports

* Use db_scalar() in notes_table_len()

* Rework CSV metadata

- Notetypes and decks are either defined by a global id or by a column.
- If a notetype id is provided, its field map must also be specified.
- If a notetype column is provided, fields are now mapped by index
instead of name at import time. So the first non-meta column is used for
the first field of every note, regardless of notetype. This makes
importing easier and should improve compatiblity with files without a
notetype column.
- Ensure first field can be mapped to a column.
- Meta columns must be defined as `#[meta name]:[column index]` instead
of in the `#columns` tag.
- Column labels contain the raw names defined by the file and must be
prettified by the frontend.

* Adjust frontend to new backend column mapping

* Add force flags for is_html and delimiter

* Detect if CSV is HTML by field content

* Update dupe resolution labels

* Simplify selectors

* Fix coalescence of oneofs in TS

* Disable meta columns from selection

Plus a lot of refactoring.

* Make import button stick to the bottom

* Write delimiter and html flag into csv

* Refetch field map after notetype change

* Fix log labels for csv import

* Log notes whose deck/notetype was missing

* Fix hiding of empty log queues

* Implement adding tags to all notes of a csv

* Fix dupe resolution not being set in log

* Implement adding tags to updated notes of a csv

* Check first note field is not empty

* Temporary fix for build on Linux/Mac

* Fix inverted html check (dae)

* Remove unused ftl string

* Delimiter → Separator

* Remove commented-out line

* Don't accept .json files

* Tweak tag ftl strings

* Remove redundant blur call

* Strip sound and add spaces in csv export

* Export HTML by default

* Fix unset deck in Mnemosyne import

Also accept both numbers and strings for notetypes and decks in JSON.

* Make DupeResolution::Update the default

* Fix missing dot in extension

* Make column indices 1-based

* Remove StickContainer from TagEditor

Fixes line breaking, border and z index on ImportCsvPage.

* Assign different key combos to tag editors

* Log all updated duplicates

Add a log field for the true number of found notes.

* Show identical notes as skipped

* Split tag-editor into separate ts module (dae)

* Add progress for CSV export

* Add progress for text import

* Tidy-ups after tag-editor split (dae)

- import-csv no longer depends on editor
- remove some commented lines
2022-06-01 20:26:16 +10:00
Abdo
5fe9447dcc
Add the media_check_did_finish hook (#1889) 2022-05-27 16:25:34 +10:00
Damien Elmes
2a9a6c5242 Avoid progress window pop-up when application not focused
A 10ms delay was chosen as it tends to result in the progress window
appearing immediately when clicking into the unfocused window, preventing
another action from being started before the progress window appears.

Closes #1873
2022-05-26 12:35:39 +10:00
Damien Elmes
383c890b0d Fix duplicate Anki icons appearing in dock
MPV was previously stored in the MacOS/ folder, which made macOS think
it should have a dock icon.

Fixes #1812
2022-05-26 11:05:36 +10:00
Damien Elmes
e50d40cedf Make editor.cleanup() idempotent
Hammering the esc key as a dialog loads can cause it to be run more
than once, leading to an error message.
2022-05-25 22:04:50 +10:00
Damien Elmes
496e074f29 Possible fix for Qt 6.3 crashes
As mentioned on #1879, the dialog.deleteLater() call appears to be
causing crashes on some systems on Qt 6.3. Explicitly destroying the page
prior to the containing webview appears to work around the issue.
2022-05-25 21:46:47 +10:00
Damien Elmes
82196753ec Rework display of available cards in custom study
In v3, it's more informative to show the count of child decks separately,
since increasing the limit of the current deck does not increase the limits
of child decks. When we rework the decks list in the future, a tooltip
will hopefully provide an easier way for users to see where cards are
available, and where limits are being applied.

Closes #1868
2022-05-20 17:52:02 +10:00
Abdo
515e77b0f4
Add the previewer_did_init hook (#1882) 2022-05-19 11:10:12 +10:00
Abdo
638286a3fc
Add the reviewer_will_replay_recording hook (#1877) 2022-05-18 13:44:56 +10:00
RumovZ
58370d6757
Fix #1874 (#1875)
Probably a race condition. `.get_row()` is not a reliable check for card
or note existence, because it returns from an outdated cache,
if the backend is currently blocked.
2022-05-18 13:34:51 +10:00
Henrik Giesel
3b8aa97396
Use same config for editor and reviewer Mathjax (#1865)
* Remove custom config and use tex-chtml-full for editor Mathjax

* Add mathjax package in /ts

* Share mathjax config between tex-svg and tex-chtml

* Use "[+]" in Mathjax config again

* Remove mention of MathJaxReady

* Satisfy eslint
2022-05-13 13:23:35 +10:00
Abdo
f22d8015a6
Add some helper functions to AVPlayer (#1864) 2022-05-13 13:08:05 +10:00
Abdo
7c543eeb2f
Add the av_player_will_play_tags hook (#1842)
A general version of the reviewer_will_play_question_sounds and reviewer_will_play_answer_sounds hooks
2022-05-09 11:08:34 +10:00
Henrik Giesel
df1f7ff96c
Replace sequences of whitespace into single space in AddTags (#1840) 2022-05-07 09:16:57 +10:00
Damien Elmes
c8a4e5ea22 Add more progress + abort points to export code
The old `media_files_did_export` hook has been kept around for use with
the legacy apkg exporter (an add-on uses it), and a new 
`legacy_export_progress` hook has been added so we can get progress
from the new colpkg exporter until we move over fully to the new code.
2022-05-06 15:32:23 +10:00
Damien Elmes
6a95141fd9 Accept .zip as an alias for .apkg
The legacy importer does this already, because some web servers and
clients sniff the content type of .apkg files, and "helpfully" rename
them to .zip
2022-05-05 21:25:59 +10:00
Damien Elmes
72389b97be Show a user-facing message instead of a traceback on invalid file type
While our importing dialog limits the types of files that can be selected,
users can also import by providing a filename on the command line.
2022-05-05 21:24:12 +10:00
Damien Elmes
fdbe211539 Support new import code in drag/drop + file double-click cases
https://forums.ankiweb.net/t/anki-2-1-52-release-candidate/19412/24
2022-05-03 14:09:40 +10:00
Matthias Metelka
567b05b731
Fix scrollbars showing on bottom bar (#1833) 2022-05-03 13:57:33 +10:00
RumovZ
5f9451f547
Add apkg import/export on backend (#1743)
* Add apkg export on backend

* Filter out missing media-paths at write time

* Make TagMatcher::new() infallible

* Gather export data instead of copying directly

* Revert changes to rslib/src/tags/

* Reuse filename_is_safe/check_filename_safe()

* Accept func to produce MediaIter in export_apkg()

* Only store file folder once in MediaIter

* Use temporary tables for gathering

export_apkg() now accepts a search instead of a deck id. Decks are
gathered according to the matched notes' cards.

* Use schedule_as_new() to reset cards

* ExportData → ExchangeData

* Ignore ascii case when filtering system tags

* search_notes_cards_into_table →

search_cards_of_notes_into_table

* Start on apkg importing on backend

* Fix due dates in days for apkg export

* Refactor import-export/package

- Move media and meta code into appropriate modules.
- Normalize/check for normalization when deserializing media entries.

* Add SafeMediaEntry for deserialized MediaEntries

* Prepare media based on checksums

- Ensure all existing media files are hashed.
- Hash incoming files during preparation to detect conflicts.
- Uniquify names of conflicting files with hash (not notetype id).
- Mark media files as used while importing notes.
- Finally copy used media.

* Handle encoding in `replace_media_refs()`

* Add trait to keep down cow boilerplate

* Add notetypes immediately instaed of preparing

* Move target_col into Context

* Add notes immediately instaed of preparing

* Note id, not guid of conflicting notes

* Add import_decks()

* decks_configs → deck_configs

* Add import_deck_configs()

* Add import_cards(), import_revlog()

* Use dyn instead of generic for media_fn

Otherwise, would have to pass None with type annotation in the default
case.

* Fix signature of import_apkg()

* Fix search_cards_of_notes_into_table()

* Test new functions in text.rs

* Add roundtrip test for apkg (stub)

* Keep source id of imported cards (or skip)

* Keep source ids of imported revlog (or skip)

* Try to keep source ids of imported notes

* Make adding notetype with id undoable

* Wrap apkg import in transaction

* Keep source ids of imported deck configs (or skip)

* Handle card due dates and original due/did

* Fix importing cards/revlog

Card ids are manually uniquified.

* Factor out card importing

* Refactor card and revlog importing

* Factor out card importing

Also handle missing parents .

* Factor out note importing

* Factor out media importing

* Maybe upgrade scheduler of apkg

* Fix parent deck gathering

* Unconditionally import static media

* Fix deck importing edge cases

Test those edge cases, and add some global test helpers.

* Test note importing

* Let import_apkg() take a progress func

* Expand roundtrip apkg test

* Use fat pointer to avoid propogating generics

* Fix progress_fn type

* Expose apkg export/import on backend

* Return note log when importing apkg

* Fix archived collection name on apkg import

* Add CollectionOpWithBackendProgress

* Fix wrong Interrupted Exception being checked

* Add ClosedCollectionOp

* Add note ids to log and strip HTML

* Update progress when checking incoming media too

* Conditionally enable new importing in GUI

* Fix all_checksums() for media import

Entries of deleted files are nulled, not removed.

* Make apkg exporting on backend abortable

* Return number of notes imported from apkg

* Fix exception printing for QueryOp as well

* Add QueryOpWithBackendProgress

Also support backend exporting progress.

* Expose new apkg and colpkg exporting

* Open transaction in insert_data()

Was slowing down exporting by several orders of magnitude.

* Handle zstd-compressed apkg

* Add legacy arg to ExportAnkiPackage

Currently not exposed on the frontend

* Remove unused import in proto file

* Add symlink for typechecking of import_export_pb2

* Avoid kwargs in pb message creation, so typechecking is not lost

Protobuf's behaviour is rather subtle and I had to dig through the docs
to figure it out: set a field on a submessage to automatically assign 
the submessage to the parent, or call SetInParent() to persist a default
version of the field you specified.

* Avoid re-exporting protobuf msgs we only use internally

* Stop after one test failure

mypy often fails much faster than pylint

* Avoid an extra allocation when extracting media checksums

* Update progress after prepare_media() finishes

Otherwise the bulk of the import ends up being shown as "Checked: 0"
in the progress window.

* Show progress of note imports

Note import is the slowest part, so showing progress here makes the UI
feel more responsive.

* Reset filtered decks at import time

Before this change, filtered decks exported with scheduling remained
filtered on import, and maybe_remove_from_filtered_deck() moved cards
into them as their home deck, leading to errors during review.

We may still want to provide a way to preserve filtered decks on import,
but to do that we'll need to ensure we don't rewrite the home decks of
cards, and we'll need to ensure the home decks are included as part of
the import (or give an error if they're not).

https://github.com/ankitects/anki/pull/1743/files#r839346423

* Fix a corner-case where due dates were shifted by a day

This issue existed in the old Python code as well. We need to include
the user's UTC offset in the exported file, or days_elapsed falls back
on the v1 cutoff calculation, which may be a day earlier or later than
the v2 calculation.

* Log conflicting note in remapped nt case

* take_fields() → into_fields()

* Alias `[u8; 20]` with `Sha1Hash`

* Truncate logged fields

* Rework apkg note import tests

- Use macros for more helpful errors.
- Split monolith into unit tests.
- Fix some unknown error with the previous test along the way.
(Was failing after 969484de4388d225c9f17d94534b3ba0094c3568.)

* Fix sorting of imported decks

Also adjust the test, so it fails without the patch. It was only passing
before, because the parent deck happened to come before the
inconsistently capitalised child alphabetically. But we want all parent
decks to be imported before their child decks, so their children can
adopt their capitalisation.

* target[_id]s → existing_card[_id]s

* export_collection_extracting_media() → ...

export_into_collection_file()

* target_already_exists→card_ordinal_already_exists

* Add search_cards_of_notes_into_table.sql

* Imrove type of apkg export selector/limit

* Remove redundant call to mod_schema()

* Parent tooltips to mw

* Fix a crash when truncating note text

String::truncate() is a bit of a footgun, and I've hit this before
too :-)

* Remove ExportLimit in favour of separate classes

* Remove OpWithBackendProgress and ClosedCollectionOp

Backend progress logic is now in ProgressManager. QueryOp can be used
for running on closed collection.

Also fix aborting of colpkg exports, which slipped through in #1817.

* Tidy up import log

* Avoid QDialog.exec()

* Default to excluding scheuling for deck list deck

* Use IncrementalProgress in whole import_export code

* Compare checksums when importing colpkgs

* Avoid registering changes if hashes are not needed

* ImportProgress::Collection → ImportProgress::File

* Make downgrading apkgs depend on meta version

* Generalise IncrementableProgress

And use it in entire import_export code instead.

* Fix type complexity lint

* Take count_map for IncrementableProgress::get_inner

* Replace import/export env with Shift click

* Accept all args from update() for backend progress

* Pass fields of ProgressUpdate explicitly

* Move update_interval into IncrementableProgress

* Outsource incrementing into Incrementor

* Mutate ProgressUpdate in progress_update callback

* Switch import/export legacy toggle to profile setting

Shift would have been nice, but the existing shortcuts complicate things.
If the user triggers an import with ctrl+shift+i, shift is unlikely to
have been released by the time our code runs, meaning the user accidentally
triggers the new code. We could potentially wait a while before bringing
up the dialog, but then we're forced to guess at how long it will take the
user to release the key.

One alternative would be to use alt instead of shift, but then we need to
trigger our shortcut when that key is pressed as well, and it could
potentially cause a conflict with an add-on that already uses that
combination.

* Show extension in export dialog

* Continue to provide separate options for schema 11+18 colpkg export

* Default to colpkg export when using File>Export

* Improve appearance of combo boxes when switching between apkg/colpkg

+ Deal with long deck names

* Convert newlines to spaces when showing fields from import

Ensures each imported note appears on a separate line

* Don't separate total note count from the other summary lines

This may come down to personal preference, but I feel the other counts
are equally as important, and separating them feels like it makes it
a bit easier to ignore them.

* Fix 'deck not normal' error when importing a filtered deck for the 2nd time

* Fix [Identical] being shown on first import

* Revert "Continue to provide separate options for schema 11+18 colpkg export"

This reverts commit 8f0b2c175f4794d642823b60414d142a12768441.

Will use a different approach

* Move legacy support into a separate exporter option; add to apkg export

* Adjust 'too new' message to also apply to .apkg import case

* Show a better message when attempting to import new apkg into old code

Previously the user could end seeing a message like:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 1: invalid start byte

Unfortunately we can't retroactively fix this for older clients.

* Hide legacy support option in older exporting screen

* Reflect change from paths to fnames in type & name

* Make imported decks normal at once

Then skip special casing in update_deck(). Also skip updating
description if new one is empty.

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2022-05-02 21:12:46 +10:00
RumovZ
1e02980133
Fix previewer runtime error "deleted" (#1830) 2022-05-02 10:40:44 +10:00
Damien Elmes
27f2e39ff9
Drop default Show Answer/Good highlight (#1820)
Feedback welcome. Discussion at
https://forums.ankiweb.net/t/2-1-5-border-around-good/19175

Partially reverts 301c9587d1
2022-04-27 19:26:16 +10:00
Damien Elmes
ee70006ec4 Reset zoom on page transition
https://forums.ankiweb.net/t/2-1-50-zooming-in-while-reviewing-results-in-an-unusably-huge-deck-list/19283
2022-04-22 15:45:50 +10:00
RumovZ
aea7eb667e
Fix progress of chained operations (#1817)
* Fix progress of chained operations

Especially aborting colpkg import.

* Notify about missing progress dialog
2022-04-22 14:47:17 +10:00
Damien Elmes
280c06425d Increase compression on zstd packages 2022-04-22 13:52:24 +10:00
Abdo
6ea75df292
Fix pasting of local links to unsupported types that contain spaces (#1813)
This change causes local links to unsupported formats like PDF to be
handled by _processUrls() instead of _processText, converting them to
correct hyperlinks in case they contain spaces.
2022-04-21 14:10:53 +10:00
Damien Elmes
6f764aeda4 Fix custom browser font not being honored
https://forums.ankiweb.net/t/on-anki-2-1-50-browser-table-font-override-is-not-respected/19259
2022-04-21 13:28:22 +10:00
Damien Elmes
031fc625fd Update Mac build to Qt 6.3 2022-04-20 21:33:31 +10:00
Damien Elmes
30d55aa553 Only require ANKI_WAYLAND if frozen
Accidentally changed `and` to `or` while testing 7115caab13.
2022-04-20 19:41:41 +10:00
Damien Elmes
da0cbfec32 Add workaround for unwanted CF_HTML header when pasting on Windows
Fixes #1751 for now; hopefully we can roll this change back once 6.3.1
is out in 3-4 weeks.
2022-04-20 17:23:11 +10:00
Damien Elmes
3031219a34 Add workaround to ensure internal pastes flagged on Windows/Qt6
Fixes #1793
2022-04-20 17:05:24 +10:00
Damien Elmes
7115caab13 Default to X11 on Qt6 builds as well
Qt6 no longer appears to require QT_QPA_PLATFORM to be set.

https://forums.ankiweb.net/t/blury-interface-with-gnome-wayland-and-fractional-scaling/19196/4
2022-04-20 14:41:01 +10:00
Damien Elmes
adbe96ca00
Load page script after body created (#1802)
document.body must exist by the time the top level Svelte component
initializes.

https://forums.ankiweb.net/t/2-1-50-editor-wont-show-when-addons-load-many-js-files/19036
2022-04-19 17:16:56 +10:00
Damien Elmes
a7cb5e210e Close browser before full sync or colpkg import/export
Closes #1797
2022-04-19 17:10:34 +10:00
Luka Warren
0835129a00
Fix issue #1114 by scrolling the user to the top of the page (#1810)
* Scroll stats to top when exporting (#1114)

It's obviously a bit of a "hacky" solution, since it's slightly jarring for users to scroll down, click export, then find themselves all the way at the top again, but it's somewhat less confusing than wondering why your PDF is broken :-)

* Clarified comment in stats.py (#1114)

* Apply scrolling fix to new stats screen, not legacy stats (dae)

Also wait for JS callback before saving the PDF, as JS is executed
asynchronously.
2022-04-19 15:39:32 +10:00
Damien Elmes
a9769813ba Add back support for custom mountpoint in card stats
The move to separate .html files broke our legacy card stats routine.

Related: d1d71ffdbb
2022-04-15 15:30:05 +10:00
Damien Elmes
24ab8ac423 Fix copying text to external apps when running on Gnome
Mutter seems to get confused if we mutate the keyboard in dataChanged().

Closes #1799
2022-04-15 12:09:56 +10:00
RumovZ
e29a5f779b
Fix selector index after programatic search (#1796) 2022-04-14 18:46:40 +10:00
Damien Elmes
29c48a60e0 Fix illegible calendar buttons in dark mode on Mac/Linux
https://forums.ankiweb.net/t/macos-apple-silicon-2-1-50-dark-mode-statistics-heatmap-buttons-dont-have-icons/18951

This button code is in need of a cleanup.
2022-04-13 13:53:45 +10:00
Damien Elmes
0b2a226dc8 Add mock stdout/stderr for console=False case on Windows
PyInstaller provided a NulWriter when running in GUI mode, but stdout/
stderr now default to None with PyOxidizer.

Fixes #1786
2022-04-09 16:48:32 +10:00
Abdo
a99253b990
Allow passing args to anki-console.bat (#1785) 2022-04-09 14:40:26 +10:00
roxgib
77d14ddf1e
Add minimumContentsLength property to templatesBox (#1781)
Addresses #1777 by adding the `minimumContentsLength` property to the comboBox, which causes the size policy to not require expanding beyond that amount while still expanding if the user stretches the window manually.

Note that users who were previously experiencing large window widths due to the previous behaviour might see the same size again due the geometry being restored.
2022-04-09 13:55:03 +10:00
Aristotelis
8100e81789
Fix a number of bugs with add-on conflict resolution (#1780)
* Always enable manually installed add-ons

Ensures that manually installed add-ons are enabled after the installation, even if previously disabled.

Prevents scenarios where users could end up with no active add-on build (e.g. when switching between stable add-on builds distributed via AnkiWeb and betas distributed via GitHub).

* Improve type annotations

* Also enable disabled AnkiWeb add-ons upon interactive installation

Applies to add-ons that users actively install via their AnkiWeb ID. Updates are exempt, preserving whatever status add-ons were in.

* Prevent disabled add-ons from triggering conflicts

* Fix download_addons() not passing on force_enable argument (dae)
2022-04-09 13:51:59 +10:00
Damien Elmes
f2bffaa185 Tweaks to video driver handling
- Use a separate `gldriver6` file for configuring Qt6 so we don't
pick up old settings, or cause problems when switching back and forth.
- Default to OpenGL/auto instead of software, as that was what we
were using throughout the beta period.
- Try to detect driver failure on startup. Untested.
- Hide the selector in the preferences again, as if Anki is unable
to automatically switch drivers, the user could change the setting
and then not be able to get back into Anki.
2022-04-06 11:35:49 +10:00
Damien Elmes
bb940cad82 Match editor background to widget background in day mode 2022-04-05 10:55:25 +10:00
Damien Elmes
e4f46463f2 Expose video driver settings on Qt6, sans ANGLE 2022-04-03 19:57:58 +10:00
Damien Elmes
04f508d664 Add link to Wayland issues page 2022-04-03 16:50:00 +10:00
Damien Elmes
9ed12bb9d0 Call browser show hook prior to initiating search
https://github.com/ankipalace/advanced-browser/issues/141
2022-04-02 21:42:49 +10:00
Henrik Giesel
5b1fcccf33
Add extra button group for cloze commands (#1756)
* First attempt at adding a directory for icons under //ts

* Fix image import

* Fix import order

* Add cloze button group

* Fix issue with toolbar.toolbar dynamically slottable

* Change tooltip for repeating cloze deletion

* Fix repeat cloze button not working on macOS (dae)
2022-03-31 13:30:00 +10:00
Damien Elmes
39c3a8e104 Add Daniel to about screen
As always, anyone who has contributed and is missing, please let me
know, or send through a PR.
2022-03-30 13:49:07 +10:00
RumovZ
f1488b5983
Card type error (#1749)
* TemplateSaveError -> CardTypeError

* Don't show success tooltip if export fails

* Attach help page to error

Show help link if export fails due to card type error.

* Add type (dae)

* Add shared show_exception() (dae)

- Use a shared routine for printing standard backend errors, so that
we can take advantage of the help links in eg. the card layout screen
as well.
- The truthiness check on help in showInfo() would have ignored the
enum 0 value.
- Close the exporting dialog on a documented failure as well

* Fix local variable help_page
2022-03-28 22:17:50 +10:00
RumovZ
dd16890c11
Add Deleted error and disable all bad browser rows (#1742)
* Add Deleted error and disable all bad browser rows

* Avoid error when opening the browse screen to a card with a missing note (dae)

* In cards mode, a missing note is NotFound, not Deleted (dae)

So we distinguish between referential integrity error, and explicit
deletion.

* Remove redundant try block
2022-03-28 19:06:19 +10:00
Damien Elmes
45970fd0d2 Stop directing users to the old add-ons support site 2022-03-28 18:54:18 +10:00
Damien Elmes
7506d5f06c Fall back on regular deletion when trash folder unavailable
aa0cac1ed3 (commitcomment-69668166)
2022-03-28 14:40:31 +10:00
Damien Elmes
d2caab6d5a Update Python deps for Waitress fix
b28c9e8bda

Closes #1731
2022-03-23 22:22:23 +10:00
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
Hikaru Y
704fb918c3
Fix NotFoundError when opening browser after switching profiles (#1725) 2022-03-21 14:45:22 +10:00
RumovZ
16fe18d033
Refactor export-import code and resolve fixmes (#1723)
* Write media files in chunks

* Test media file writing

* Add iter `ReadDirFiles`

* Remove ImportMediaError, fail fatally instead

Partially reverts commit f8ed4d89ba.

* Compare hashes of media files to be restored

* Improve `MediaCopier::copy()`

* Restore media files atomically with tempfile

* Make downgrade flag an enum

* Remove SchemaVersion::Latest in favour of Option

* Remove sha1 comparison again

* Remove unnecessary repr(u8) (dae)
2022-03-18 19:31:55 +10:00
Damien Elmes
f8ed4d89ba Add new error variant to frontend; ensure errors are mapped appropriately 2022-03-17 20:58:35 +10:00
Damien Elmes
bdfa8387a5 Handle export failures better
- Ensure collection reopened even on failure
- Don't display a traceback to the user
2022-03-17 17:59:47 +10:00
Damien Elmes
c2e8d89fc6
Colpkg fixes (#1722)
* Fix legacy colpkg import; disable v3 import/export; add roundtrip test

The test has revealed we weren't decompressing the media files on v3
import. That's easy to fix, but means all files need decompressing
even when they already exist, which is not ideal - it would be better
to store size/checksum in the metadata instead.

* Switch media and meta to protobuf; re-enable v3 import/export

- Fixed media not being decompressed on import
- The uncompressed size and checksum is now included for each media
entry, so that we can quickly check if a given file needs to be extracted.
We're still just doing a naive size comparison on colpkg import at the
moment, but we may want to use a checksum in the future, and will need
a checksum for apkg imports.
- Checksums can't be efficiently encoded in JSON, so the media list
has been switched to protobuf to reduce the the space requirements.
- The meta file has been switched to protobuf as well, for consistency.
This will mean any colpkg files exported with beta7 will be
unreadable.

* Avoid integer version comparisons

* Re-enable v3 test

* Apply suggestions from code review

Co-authored-by: RumovZ <gp5glkw78@relay.firefox.com>

* Add export_colpkg() method to Collection

More discoverable, and easier to call from unit tests

* Split import/export code out into separate folders

Currently colpkg/*.rs contain some routines that will be useful for
apkg import/export as well; in the future we can refactor them into a
separate file in the parent module.

* Return a proper error when media import fails

This tripped me up when writing the earlier unit test - I had called
the equivalent of import_colpkg()?, and it was returning a string error
that I didn't notice. In practice this should result in the same text
being shown in the UI, but just skips the tooltip.

* Automatically create media folder on import

* Move roundtrip test into separate file; check collection too

* Remove zstd version suffix

Prevents a warning shown each time Rust Analyzer is used to check the
code.

Co-authored-by: RumovZ <gp5glkw78@relay.firefox.com>
2022-03-17 15:11:23 +10:00
Henrik Giesel
2d00b6659f
Fix add-on usages of addMedia (#1721)
* Expose old .addMedia again, and use a new resolve_media for built-in uses

* Add an explaining comment for addMedia

* Add some docstrings (dae)
2022-03-16 10:29:06 +10:00
Damien Elmes
f3e81c8a95 Move custom study tag and limit gathering+saving into the backend
Ideally this would have been in beta 6 :-) No add-ons appear to be
using customstudy.py/taglimit.py though, so it should hopefully not be
disruptive.

In the earlier custom study changes, we didn't get around to addressing
issue #1136. Now instead of trying to determine the maximum increase
to allow (which doesn't work correctly with nested decks), we just
present the total available to the user again, and let them decide. There's
plenty of room for improvement here still, but further work here might
be better done once we look into decoupling deck limits from deck presets.

Tags and available cards are fetched prior to showing the dialog now,
and will show a progress dialog if things take a while.

Tags are stored in an aux var now, so they don't inflate the deck
object size.
2022-03-10 16:23:03 +10:00
Damien Elmes
d1a43a2d42 Invoke mypy from within runfiles
tools/mypy-watch now prints .py paths relative to the workspace root,
which makes it easy to click on them to jump to the relevant file/line
in VS Code.
2022-03-10 12:02:04 +10:00
Damien Elmes
a495fbaa8d Try again if dmg detach fails 2022-03-09 19:01:20 +10:00
RumovZ
b9c3b12f71
Optionally restore original position and reset counts when forgetting (#1714)
* Add forget prompt with options

- Restore original position
- Reset reps and lapses

* Restore position when resetting for export

* Add config context to avoid passing keys

* Add routine to fetch defaults; use method-specific enum (dae)

* Keep original position by default (dae)

* Fix code completion for forget dialog (dae)

Needs to be a symbolic link to the generated file
2022-03-09 16:51:41 +10:00
RumovZ
c21e6e2b97
Disable full screen on Windows with OpenGL (#1715) 2022-03-09 14:21:54 +10:00
RumovZ
f3c8857421
Backups (#1685)
* Add zstd dep

* Implement backend backup with zstd

* Implement backup thinning

* Write backup meta

* Use new file ending anki21b

* Asynchronously backup on collection close in Rust

* Revert "Add zstd dep"

This reverts commit 3fcb2141d2be15f907269d13275c41971431385c.

* Add zstd again

* Take backup col path from col struct

* Fix formatting

* Implement backup restoring on backend

* Normalize restored media file names

* Refactor `extract_legacy_data()`

A bit cumbersome due to borrowing rules.

* Refactor

* Make thinning calendar-based and gradual

* Consider last kept backups of previous stages

* Import full apkgs and colpkgs with backend

* Expose new backup settings

* Test `BackupThinner` and make it deterministic

* Mark backup_path when closing optional

* Delete leaky timer

* Add progress updates for restoring media

* Write restored collection to tempfile first

* Do collection compression in the background thread

This has us currently storing an uncompressed and compressed copy of
the collection in memory (not ideal), but means the collection can be
closed without waiting for compression to complete. On a large collection,
this takes a close and reopen from about 0.55s to about 0.07s. The old
backup code for comparison: about 0.35s for compression off, about
8.5s for zip compression.

* Use multithreading in zstd compression

On my system, this reduces the compression time of a large collection
from about 0.55s to 0.08s.

* Stream compressed collection data into zip file

* Tweak backup explanation

+ Fix incorrect tab order for ignore accents option

* Decouple restoring backup and full import

In the first case, no profile is opened, unless the new collection
succeeds to load.
In the second case, either the old collection is reloaded or the new one
is loaded.

* Fix number gap in Progress message

* Don't revert backup when media fails but report it

* Tweak error flow

* Remove native BackupLimits enum

* Fix type annotation

* Add thinning test for whole year

* Satisfy linter

* Await async backup to finish

* Move restart disclaimer out of backup tab

Should be visible regardless of the current tab.

* Write restored collection in chunks

* Refactor

* Write media in chunks and refactor

* Log error if removing file fails

* join_backup_task -> await_backup_completion

* Refactor backup.rs

* Refactor backup meta and collection extraction

* Fix wrong error being returned

* Call sync_all() on new collection

* Add ImportError

* Store logger in Backend, instead of creating one on demand

init_backend() accepts a Logger rather than a log file, to allow other
callers to customize the logger if they wish.

In the future we may want to explore using the tracing crate as an
alternative; it's a bit more ergonomic, as a logger doesn't need to be
passed around, and it plays more nicely with async code.

* Sync file contents prior to rename; sync folder after rename.

* Limit backup creation to once per 30 min

* Use zstd::stream::copy_decode

* Make importing abortable

* Don't revert if backup media is aborted

* Set throttle implicitly

* Change force flag to minimum_backup_interval

* Don't attempt to open folders on Windows

* Join last backup thread before starting new one

Also refactor.

* Disable auto sync and backup when restoring again

* Force backup on full download

* Include the reason why a media file import failed, and the file path

- Introduce a FileIoError that contains a string representation of
the underlying I/O error, and an associated path. There are a few
places in the code where we're currently manually including the filename
in a custom error message, and this is a step towards a more consistent
approach (but we may be better served with a more general approach in
the future similar to Anyhow's .context())
- Move the error message into importing.ftl, as it's a bit neater
when error messages live in the same file as the rest of the messages
associated with some functionality.

* Fix importing of media files

* Minor wording tweaks

* Save an allocation

I18n strings with replacements are already strings, so we can skip the
extra allocation. Not that it matters here at all.

* Terminate import if file missing from archive

If a third-party tool is creating invalid archives, the user should know
about it. This should be rare, so I did not attempt to make it
translatable.

* Skip multithreaded compression on small collections

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2022-03-07 15:11:31 +10:00
RumovZ
8504bd67ed
Fix bury count (more) (#1712)
* Fix bury count for negative values

* Enhance bury count tooltip

* Please type checker
2022-03-07 11:03:14 +10:00
Damien Elmes
4066518808 Clean up webview after fields dialog closed
https://github.com/ankitects/anki/pull/1706#issuecomment-1058056161
2022-03-04 17:23:28 +10:00
Henrik Giesel
76bdfb3899
Add a flag to allow loading the fields dialog in a web view (#1706)
* Load fields_web from fields.py if appropriate flag is set

* Add FieldsPage as entry for new fields view

* Pass mypy

* Fix pylint

* Fix fields_web in Qt5 (dae)

May not be related to the CI error, but required for compatibility
with Qt5.
2022-03-03 22:45:26 +10:00
Damien Elmes
a06036b8aa Disable buried counts on overview when v2 scheduler in use
https://forums.ankiweb.net/t/fatal-bug-anki-2-1-50-beta5-buried-bug/17969
2022-03-03 20:12:54 +10:00
RumovZ
508b5ab947
Remove top_deck_id arg in deck_tree() (#1702)
Counts don't propogate correctly anymore (#1678).
2022-03-02 15:30:32 +10:00
PatricCunhaforWork
1219dd8f9e
Add silent option for uninstaller (#1690)
* Add /S option for unattended uninstall

* Add email to contributors
2022-03-02 13:55:57 +10:00
Damien Elmes
6ae24652e5 Fix add-on config screen failing to show in bundled build
md_in_html imports fine when done manually; it is likely PyOxidizer
has not instrumented import_module().

  File "aqt.addons", line 631, in addonConfigHelp
  File "markdown.core", line 386, in markdown
  File "markdown.core", line 96, in __init__
  File "markdown.core", line 123, in registerExtensions
  File "markdown.core", line 162, in build_extension
  File "importlib", line 127, in import_module
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 984, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'md_in_html'
2022-02-28 20:49:35 +10:00
Damien Elmes
1165939271 Update Python deps, including stable Black
Black 22.1 made some changes that required some minor reformatting.
2022-02-25 15:26:16 +10:00
Damien Elmes
d52c36e920 Make flag changes undoable again
The previous change in 1871b57663 failed
to consider the browser refreshing case, as reported here:
https://forums.ankiweb.net/t/anki-2-1-50-beta-3-4/17501/30

I previously attempted to solve this by having SetFlag skip the queue
rebuild, then mutating the captured mtimes in the queues. That didn't
work correctly when undoing, as the queue mutations weren't recorded.
This approach combines that attempt and the previous change: flag
setting is an undoable operation again, but does not change the card's
modification time, so it can be applied/undone without a queue build
being required. Instead of special-casing flag changes in the review
screen, we now just redraw the flag on changes.card, as any other card
op will have triggered a queue rebuild.
2022-02-25 15:06:07 +10:00
Henrik Giesel
0d83581ab0
Fix insert media always insert at the start (on Windows) (#1684)
* Move Trigger into its own file

* Try implement HandlerList

* Implement new input handler and handler-list

* Use new refocus HandlerList in TextColorButton

* Fix TextColorButton on windows

* Move ColorPicker to editor-toolbar

* Change trigger behavior of overwriteSurround

* Fix mathjax-overlay flushCaret

* Insert image via bridgeCommand return value

* Fix invoking color picker with F8

* Have remove format work even when collapsed

* Satisfy formatter

* Insert media via callback resolved from python

* Replace print with web.eval

* Fix python formatting

* remove unused function (dae)
2022-02-25 10:59:06 +10:00
RumovZ
a0d0f2f8fd
Add progress.single_shot() (#1683)
* Add progress.single_shot()

* Fix periodic garbage collection

* Properly cleanup mediasync timers

* Revert some replacements with `single_shot()`

These timers shouldn't fire if their widget is destroyed.

* Add timer docs explaining issues and alternatives

* Apply suggestions from code review

* Tweak docstrings
2022-02-24 21:15:56 +10:00