Porting add-ons to Anki 2.1
---------------------------

Python 3
---------

Anki 2.1 requires Python 3.5 or later. After installing Python 3 on your
machine, you can use the 2to3 tool to automatically convert your existing
scripts to Python 3 code on a folder by folder basis, like:

2to3-3.5 --output-dir=aqt3 -W -n aqt
mv aqt aqt-old
mv aqt3 aqt

Most simple code can be converted automatically, but there may be parts of the
code that you need to manually modify.

Qt5 / PyQt5
------------

The syntax for connecting signals and slots has changed in PyQt5. Recent PyQt4
versions support the new syntax as well, so after updating your add-ons you
may find they still work in Anki 2.0.x as well.

More info is available at
http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

One add-on author reported that the following tool was useful to automatically
convert the code:
https://github.com/rferrazz/pyqt4topyqt5

Compatibility with Anki 2.0
----------------------------

It should be possible for many add-ons to support both Anki 2.0 and 2.1 at the
same time.

Most Python 3 code will run on Python 2 as well, though extra work may be
required when dealing with file access and byte strings.

The Qt modules are in 'PyQt5' instead of 'PyQt4'. You can do a conditional
import, but an easier way is to import from aqt.qt - eg "from aqt.qt import *"

The most difficult part is the change from the unsupported QtWebKit to
QtWebEngine. If you do any non-trivial work with webviews, some work will be
required to port your code to Anki 2.1, as described in the next section.

If you find that non-trivial changes are required to get your add-on working
with Anki 2.1, the easiest option is to drop support for older Anki versions.
Please see the 'sharing updated add-ons' section below for more information.

Webview changes
----------------

Qt 5 has dropped WebKit in favour of the Chromium-based WebEngine, so
Anki's webviews are now using WebEngine. Of note:

- You can now debug the webviews using an external Chrome instance, by setting
  the env var QTWEBENGINE_REMOTE_DEBUGGING to 8080 prior to starting Anki,
  then surfing to localhost:8080 in Chrome.
- WebEngine uses a different method of communicating back to Python.
  AnkiWebView() is a wrapper for webviews which provides a pycmd(str) function in
  Javascript which will call the ankiwebview's onBridgeCmd(str) method. Various
  parts of Anki's UI like reviewer.py and deckbrowser.py have had to be
  modified to use this.
- Javascript is evaluated asynchronously, so if you need the result of a JS
  expression you can use ankiwebview's evalWithCallback().
- As a result of this asynchronous behaviour, editor.saveNow() now requires a
  callback. If your add-on performs actions in the browser, you likely need to
  call editor.saveNow() first and then run the rest of your code in the callback.
  Calls to .onSearch() will need to be changed to .search()/.onSearchActivated()
  as well. See the browser's .deleteNotes() for an example.
- Various operations that were supported by WebKit like setScrollPosition() now
need to be implemented in javascript.
- Page actions like mw.web.triggerPageAction(QWebEnginePage.Copy) are also
asynchronous, and need to be rewritten to use javascript or a delay.
- WebEngine doesn't provide a keyPressEvent() like WebKit did, so the code
that catches shortcuts not attached to a menu or button has had to be changed.
See the way reviewer.py calls setStateShortcuts() for an example.

Add-ons without a top level file
---------------------------------

Add-ons no longer require a top level file - if you just distribute a single
folder, the folder's __init__.py file will form the entry point. This will not
work in 2.0.x however.

Sharing updated add-ons
------------------------

If you've succeeded in making an add-on that supports both 2.0.x and 2.1.x at
the same time, please feel free to upload it to the shared add-ons area, and
mention in the description that it works with both versions.

If you've decided to make a separate 2.1.x version, it's probably best to just
post a link to it in your current add-on description or upload it separately.
When we get closer to a release I'll look into adding separate uploads for the
two versions.
