From d8669835d859abbf26cc95fe61a90dd349c6b279 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:37:50 -0800 Subject: [PATCH 01/10] aqt.exporter takes extra argument cid --- pylib/anki/exporting.py | 2 +- qt/aqt/exporting.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index 84196f5c5..6be5bf0a0 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 diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index 964685927..a97eb7ce3 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,17 +15,18 @@ 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 From 9fdc885d8259183ba492acacfa40abf4e4d5c789 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:38:20 -0800 Subject: [PATCH 02/10] anki.exporter takes extra argument cids --- pylib/anki/exporting.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index 6be5bf0a0..d1f549bed 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -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") From c02ff8593a2faa7e3aa076ce0a262cd3dfde8b44 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:13:25 -0800 Subject: [PATCH 03/10] cardIds return cids if it is set --- pylib/anki/exporting.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index d1f549bed..40a811f37 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -73,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) From d48111af6845d2db39fe47633e60d7c4e651c6ff Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:43:19 -0800 Subject: [PATCH 04/10] inverse if/else in deckIds --- pylib/anki/exporting.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index 40a811f37..a454ed370 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -170,10 +170,10 @@ class AnkiExporter(Exporter): Exporter.__init__(self, col) def deckIds(self) -> List[int]: - if not self.did: - return [] - else: + if 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 From e70a317ac58a63c655d5e391467408837d2fc0af Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:48:59 -0800 Subject: [PATCH 05/10] ofCids: returns did of all cids --- pylib/anki/decks.py | 3 +++ 1 file changed, 3 insertions(+) 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 From b5fed631d5da14291e750efaf525bc342469bb77 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:49:28 -0800 Subject: [PATCH 06/10] deckIds return deck of selected cards --- pylib/anki/exporting.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index a454ed370..c6ba97f20 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -170,7 +170,9 @@ class AnkiExporter(Exporter): Exporter.__init__(self, col) def deckIds(self) -> List[int]: - if self.did: + 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 [] From a6567da25956cd1fb462e163438afbfbe8b58875 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:19:37 -0800 Subject: [PATCH 07/10] if cards are selected, default is apkg --- qt/aqt/exporting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index a97eb7ce3..e95df631a 100644 --- a/qt/aqt/exporting.py +++ b/qt/aqt/exporting.py @@ -30,7 +30,7 @@ class ExportDialog(QDialog): 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 From 272db65f0a54e3ef83db7ae2d7c016d38edd07df Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 8 Feb 2020 22:26:11 -0800 Subject: [PATCH 08/10] Replace list of deck by "Browser Selection" --- qt/aqt/exporting.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index e95df631a..731544b2d 100644 --- a/qt/aqt/exporting.py +++ b/qt/aqt/exporting.py @@ -40,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...")) @@ -79,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: From 617043f632416512e626e36f8301270ea23eef71 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 9 Feb 2020 19:15:10 -0800 Subject: [PATCH 09/10] browser._exporting --- qt/aqt/browser.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 36026759c..abe70faa7 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -1898,6 +1898,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 ###################################################################### From a087d0e4c480ba577d8378311357edd4e3f4e2de Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 9 Feb 2020 19:15:19 -0800 Subject: [PATCH 10/10] Adding export option in Browser --- qt/aqt/browser.py | 2 ++ qt/designer/browser.ui | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index abe70faa7..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) 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 @@ + @@ -599,6 +600,14 @@ Ctrl+K + + + &Export Notes + + + Ctrl+Shift+E + +