2.0 版アドオンの移植

Python 3

Anki 2.1 には Python 3 以降が必要です。Python 3 をマシンにインストールした後、2to3 ツールを使用して、以下のように既存のスクリプトをフォルダごとに Python 3 コードに自動的に変換することができます:

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

単純なコードのほとんどは自動的に変換できますが、手動で修正する必要がある部分があるかもしれません。

Qt5 / PyQt5

PyQt5では、シグナルとスロットを接続するための構文が変更されました。最近の PyQt4 バージョンでは新しい構文もサポートしているので、Anki 2.0 と 2.1 の両方のアドオンに同じ構文を使用することができます。

詳細は、http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html にあります。

あるアドオン作者は、コードを自動変換するために、以下のツールが便利であったと報告しています。 https://github.com/rferrazz/pyqt4topyqt5

Qt モジュールは PyQt4 ではなく PyQt5 になっています。条件付きでインポートすることもできますが、より簡単な方法は、次のように aqt.qt からインポートすることです:

from aqt.qt import *

これにより、Qt のバージョンを指定することなく、QDialog のようなすべての Qt オブジェクトをインポートすることができます。

単一の .py アドオンには専用のフォルダが必要

各アドオンは独自のフォルダに格納されるようになりました。もし、あなたのアドオンが以前は demo.py という名前だった場合、demo フォルダを作成して __init__.py ファイルを作成する必要があります。

2.0 との互換性を気にしないのであれば、 demo.pydemo/__init__.py にリネームすればよいでしょう。

もし、同じファイルで 2.0 に対応するつもりなら、元のファイルをフォルダにコピーし(demo.pydemo/demo.py )、demo/__init__.py に以下を追加して相対的にインポートすることが可能です:

from . import demo

AnkiWeb にアップロードする際は、フォルダを ZIP で圧縮する必要があります。詳しくは、アドオンの共有を参照してください。

アップグレード時にフォルダが削除される

アドオンをアップグレードすると、アドオンフォルダ内のファイルはすべて削除されます。唯一の例外は、特別な user_files folder です。アドオンが単純なキー/値設定以上のものを必要とする場合、関連するファイルを user_files フォルダに保存していることを確認してください。そうしなければ、アップグレード時に失われるでしょう。

1つのコードベースで 2.0 と 2.1 の両方に対応する

Python 3 のコードのほとんどは Python 2 でも実行できるため、Anki 2.0 と 2.1 の両方で実行できるようにアドオンを更新することができます。その価値があるかどうかは、必要な変更によります。

スケジューラに影響を与えるほとんどのアドオンは、2.1 で動作させるためにわずかな変更で済むはずです。レビューア、ブラウザ、エディタの動作を変更するアドオンは、より多くの作業を必要とする可能性があります。

最も難しいのは、サポートされていないQtWebKit から QtWebEngine への変更です。WebView を使用する場合、Anki 2.1 にコードを移植する作業が必要になり、1 つのコード ベースで両方の Anki バージョンをサポートすることが難しくなる可能性があります。

アドオンが修正なしで動作する場合や、わずかな変更で済む場合は、コードに if 文を追加して、2.0.x と 2.1.x の両方に同じファイルをアップロードするのが最も簡単でしょう。

アドオンに大幅な変更が必要な場合は、2.0.x の更新を停止するか、2 つの Anki バージョン用に別々のファイルを維持する方が簡単かもしれません。

Webview の変更

Qt 5 では WebKit が廃止され、Chromium ベースの WebEngine が採用されたため、Anki のウェブビューは WebEngine を使用するようになりました。注目すべきは以下の点です :

  • Anki を起動する前に環境変数 QTWEBENGINE_REMOTE_DEBUGGING を 8080 に設定し、Chrome で localhost:8080 にアクセスすると、外部の Chrome インスタンスを使用して WebView をデバッグすることができるようになりました。

  • WebEngine は、Python に戻る通信に別の方法を使用します。AnkiWebView() はウェブビューのラッパーで、Javascript で pycmd(str) 関数を提供し、ankiwebview の onBridgeCmd(str) メソッドを呼び出すことができます。reviewer.py や deckbrowser.py など、Anki の UI のさまざまな部分は、これを使用するために修正する必要がありました。

  • Javascript は非同期に評価されるので、JS 式の結果が必要な場合は、ankiwebview の evalWithCallback() を使用します。

  • この非同期動作の結果、editor.saveNow()はコールバックを必要とするようになりました。アドオンがブラウザ上でアクションを実行する場合、まず editor.saveNow() を呼び出し、その後コールバックで残りのコードを実行する必要があるでしょう。.onSearch()への呼び出しは、同様に .search()/.onSearchActivated() に変更する必要があります。例として、ブラウザの .deleteNotes() を参照してください。

  • setScrollPosition() のように WebKit でサポートされていたさまざまな操作は、javascript で実装する必要があります。

  • mw.web.triggerPageAction(QWebEnginePage.Copy) のようなページアクションも非同期なので、JavaScript や遅延を使うように書き直す必要があります。

  • WebEngine は WebKit のようにkeyPressEvent() を提供しないので、メニューやボタンに付属しないショートカットをキャッチするコードを変更する必要がありました。 setStateShortcuts() は、与えられた状態に対するショートカットを調整するために使用するフックを発生させます。

Reviewer の変更

Anki は、前のカードをフェードアウトしてから次のカードをフェードインするようになったため、showQuestion フックが発生したときに次のカードが DOM に表示されなくなります。適切なタイミングで Javascript を実行するために使用できる新しいフックがいくつかあります - 詳しくは こちら をご覧ください。

アドオンの設定

2.0 の小さなアドオンの多くは、ユーザーがソースコードを編集してカスタマイズすることに依存していました。これは、2.1 ではもはや良いアイデアではありません。なぜなら、ユーザーによってなされた変更は、アップデートをチェックしダウンロードするときに上書きされるからです。2.1 では、これを回避するために 設定 のシステムを提供しています。2.0 もサポートし続ける必要がある場合は、以下のようなコードを使用することができます:

if getattr(getattr(mw, "addonManager", None), "getConfig", None):
    config = mw.addonManager.getConfig(__name__)
else:
    config = dict(optionA=123, optionB=456)