diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py
index c2998896f..605404d5b 100644
--- a/pylib/anki/decks.py
+++ b/pylib/anki/decks.py
@@ -470,6 +470,9 @@ class DeckManager:
dids.append(id)
return self.col.db.list("select id from cards where did in " + ids2str(dids))
+ def for_card_ids(self, cids: List[int]) -> List[int]:
+ return self.col.db.list(f"select did from cards where id in {ids2str(cids)}")
+
def _recoverOrphans(self) -> None:
dids = list(self.decks.keys())
mod = self.col.db.mod
diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py
index 84196f5c5..c6ba97f20 100644
--- a/pylib/anki/exporting.py
+++ b/pylib/anki/exporting.py
@@ -8,7 +8,7 @@ import shutil
import unicodedata
import zipfile
from io import BufferedWriter
-from typing import Any, Dict, List, Tuple, Union
+from typing import Any, Dict, List, Optional, Tuple, Union
from zipfile import ZipFile
from anki import hooks
@@ -21,9 +21,17 @@ from anki.utils import ids2str, namedtmp, splitFields, stripHTML
class Exporter:
includeHTML: Union[bool, None] = None
- def __init__(self, col: _Collection, did: None = None) -> None:
+ did: Optional[int]
+
+ def __init__(
+ self,
+ col: _Collection,
+ did: Optional[int] = None,
+ cids: Optional[List[int]] = None,
+ ) -> None:
self.col = col
self.did = did
+ self.cids = cids
def doExport(self, path) -> None:
raise Exception("not implemented")
@@ -65,7 +73,9 @@ class Exporter:
return s
def cardIds(self) -> Any:
- if not self.did:
+ if self.cids is not None:
+ cids = self.cids
+ elif not self.did:
cids = self.col.db.list("select id from cards")
else:
cids = self.col.decks.cids(self.did, children=True)
@@ -160,10 +170,12 @@ class AnkiExporter(Exporter):
Exporter.__init__(self, col)
def deckIds(self) -> List[int]:
- if not self.did:
- return []
- else:
+ if self.cids:
+ return self.col.decks.for_card_ids(self.cids)
+ elif self.did:
return [self.did] + [x[1] for x in self.src.decks.children(self.did)]
+ else:
+ return []
def exportInto(self, path: str) -> None:
# sched info+v2 scheduler not compatible w/ older clients
diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py
index 36026759c..04e4ee3f4 100644
--- a/qt/aqt/browser.py
+++ b/qt/aqt/browser.py
@@ -23,6 +23,7 @@ from anki.notes import Note
from anki.utils import fmtTimeSpan, htmlToTextLine, ids2str, intTime, isMac, isWin
from aqt import AnkiQt, gui_hooks
from aqt.editor import Editor
+from aqt.exporting import ExportDialog
from aqt.qt import *
from aqt.sound import av_player, play_clicked_audio
from aqt.theme import theme_manager
@@ -614,6 +615,7 @@ class Browser(QMainWindow):
f.actionOrange_Flag.triggered.connect(lambda: self.onSetFlag(2))
f.actionGreen_Flag.triggered.connect(lambda: self.onSetFlag(3))
f.actionBlue_Flag.triggered.connect(lambda: self.onSetFlag(4))
+ f.actionExport.triggered.connect(lambda: self._exporting())
# jumps
f.actionPreviousCard.triggered.connect(self.onPreviousCard)
f.actionNextCard.triggered.connect(self.onNextCard)
@@ -1898,6 +1900,14 @@ update cards set usn=?, mod=?, did=? where id in """
self.model.reset()
self.mw.requireReset()
+ # Exporting
+ ######################################################################
+
+ def _exporting(self):
+ cids = self.selectedNotesAsCards()
+ if cids:
+ ExportDialog(self.mw, cids=cids)
+
# Flags & Marking
######################################################################
diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py
index 964685927..731544b2d 100644
--- a/qt/aqt/exporting.py
+++ b/qt/aqt/exporting.py
@@ -4,6 +4,7 @@
import os
import re
import time
+from typing import List, Optional
import aqt
from anki import hooks
@@ -14,21 +15,22 @@ from aqt.utils import checkInvalidFilename, getSaveFile, showInfo, showWarning,
class ExportDialog(QDialog):
- def __init__(self, mw, did=None):
+ def __init__(self, mw, did: Optional[int] = None, cids: Optional[List[int]] = None):
QDialog.__init__(self, mw, Qt.Window)
self.mw = mw
self.col = mw.col
self.frm = aqt.forms.exporting.Ui_ExportDialog()
self.frm.setupUi(self)
self.exporter = None
+ self.cids = cids
self.setup(did)
self.exec_()
- def setup(self, did):
+ def setup(self, did: Optional[int]):
self.exporters = exporters()
# if a deck specified, start with .apkg type selected
idx = 0
- if did:
+ if did or self.cids:
for c, (k, e) in enumerate(self.exporters):
if e.ext == ".apkg":
idx = c
@@ -38,7 +40,10 @@ class ExportDialog(QDialog):
self.frm.format.activated.connect(self.exporterChanged)
self.exporterChanged(idx)
# deck list
- self.decks = [_("All Decks")] + sorted(self.col.decks.allNames())
+ if self.cids is None:
+ self.decks = [_("All Decks")] + sorted(self.col.decks.allNames())
+ else:
+ self.decks = [_("Browser Selection")]
self.frm.deck.addItems(self.decks)
# save button
b = QPushButton(_("Export..."))
@@ -77,9 +82,18 @@ class ExportDialog(QDialog):
self.exporter.includeMedia = self.frm.includeMedia.isChecked()
self.exporter.includeTags = self.frm.includeTags.isChecked()
self.exporter.includeHTML = self.frm.includeHTML.isChecked()
- if not self.frm.deck.currentIndex():
+ idx = self.frm.deck.currentIndex()
+ if self.cids is not None:
+ # Browser Selection
+ self.exporter.cids = self.cids
self.exporter.did = None
+ elif idx == 0:
+ # All decks
+ self.exporter.did = None
+ self.exporter.cids = None
else:
+ # Deck idx-1 in the list of decks
+ self.exporter.cids = None
name = self.decks[self.frm.deck.currentIndex()]
self.exporter.did = self.col.decks.id(name)
if self.isVerbatim:
diff --git a/qt/designer/browser.ui b/qt/designer/browser.ui
index 8e5944bbc..e400b993d 100644
--- a/qt/designer/browser.ui
+++ b/qt/designer/browser.ui
@@ -295,6 +295,7 @@
+