mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Merge pull request #443 from Arthur-Milchior/exportFromBrowserInAnki
Export from browser in anki
This commit is contained in:
commit
60becbf480
5 changed files with 59 additions and 11 deletions
|
@ -470,6 +470,9 @@ class DeckManager:
|
||||||
dids.append(id)
|
dids.append(id)
|
||||||
return self.col.db.list("select id from cards where did in " + ids2str(dids))
|
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:
|
def _recoverOrphans(self) -> None:
|
||||||
dids = list(self.decks.keys())
|
dids = list(self.decks.keys())
|
||||||
mod = self.col.db.mod
|
mod = self.col.db.mod
|
||||||
|
|
|
@ -8,7 +8,7 @@ import shutil
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import zipfile
|
import zipfile
|
||||||
from io import BufferedWriter
|
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 zipfile import ZipFile
|
||||||
|
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
@ -21,9 +21,17 @@ from anki.utils import ids2str, namedtmp, splitFields, stripHTML
|
||||||
class Exporter:
|
class Exporter:
|
||||||
includeHTML: Union[bool, None] = None
|
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.col = col
|
||||||
self.did = did
|
self.did = did
|
||||||
|
self.cids = cids
|
||||||
|
|
||||||
def doExport(self, path) -> None:
|
def doExport(self, path) -> None:
|
||||||
raise Exception("not implemented")
|
raise Exception("not implemented")
|
||||||
|
@ -65,7 +73,9 @@ class Exporter:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def cardIds(self) -> Any:
|
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")
|
cids = self.col.db.list("select id from cards")
|
||||||
else:
|
else:
|
||||||
cids = self.col.decks.cids(self.did, children=True)
|
cids = self.col.decks.cids(self.did, children=True)
|
||||||
|
@ -160,10 +170,12 @@ class AnkiExporter(Exporter):
|
||||||
Exporter.__init__(self, col)
|
Exporter.__init__(self, col)
|
||||||
|
|
||||||
def deckIds(self) -> List[int]:
|
def deckIds(self) -> List[int]:
|
||||||
if not self.did:
|
if self.cids:
|
||||||
return []
|
return self.col.decks.for_card_ids(self.cids)
|
||||||
else:
|
elif self.did:
|
||||||
return [self.did] + [x[1] for x in self.src.decks.children(self.did)]
|
return [self.did] + [x[1] for x in self.src.decks.children(self.did)]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
def exportInto(self, path: str) -> None:
|
def exportInto(self, path: str) -> None:
|
||||||
# sched info+v2 scheduler not compatible w/ older clients
|
# sched info+v2 scheduler not compatible w/ older clients
|
||||||
|
|
|
@ -23,6 +23,7 @@ from anki.notes import Note
|
||||||
from anki.utils import fmtTimeSpan, htmlToTextLine, ids2str, intTime, isMac, isWin
|
from anki.utils import fmtTimeSpan, htmlToTextLine, ids2str, intTime, isMac, isWin
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.editor import Editor
|
from aqt.editor import Editor
|
||||||
|
from aqt.exporting import ExportDialog
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.sound import av_player, play_clicked_audio
|
from aqt.sound import av_player, play_clicked_audio
|
||||||
from aqt.theme import theme_manager
|
from aqt.theme import theme_manager
|
||||||
|
@ -614,6 +615,7 @@ class Browser(QMainWindow):
|
||||||
f.actionOrange_Flag.triggered.connect(lambda: self.onSetFlag(2))
|
f.actionOrange_Flag.triggered.connect(lambda: self.onSetFlag(2))
|
||||||
f.actionGreen_Flag.triggered.connect(lambda: self.onSetFlag(3))
|
f.actionGreen_Flag.triggered.connect(lambda: self.onSetFlag(3))
|
||||||
f.actionBlue_Flag.triggered.connect(lambda: self.onSetFlag(4))
|
f.actionBlue_Flag.triggered.connect(lambda: self.onSetFlag(4))
|
||||||
|
f.actionExport.triggered.connect(lambda: self._exporting())
|
||||||
# jumps
|
# jumps
|
||||||
f.actionPreviousCard.triggered.connect(self.onPreviousCard)
|
f.actionPreviousCard.triggered.connect(self.onPreviousCard)
|
||||||
f.actionNextCard.triggered.connect(self.onNextCard)
|
f.actionNextCard.triggered.connect(self.onNextCard)
|
||||||
|
@ -1898,6 +1900,14 @@ update cards set usn=?, mod=?, did=? where id in """
|
||||||
self.model.reset()
|
self.model.reset()
|
||||||
self.mw.requireReset()
|
self.mw.requireReset()
|
||||||
|
|
||||||
|
# Exporting
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
def _exporting(self):
|
||||||
|
cids = self.selectedNotesAsCards()
|
||||||
|
if cids:
|
||||||
|
ExportDialog(self.mw, cids=cids)
|
||||||
|
|
||||||
# Flags & Marking
|
# Flags & Marking
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
@ -14,21 +15,22 @@ from aqt.utils import checkInvalidFilename, getSaveFile, showInfo, showWarning,
|
||||||
|
|
||||||
|
|
||||||
class ExportDialog(QDialog):
|
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)
|
QDialog.__init__(self, mw, Qt.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.col = mw.col
|
self.col = mw.col
|
||||||
self.frm = aqt.forms.exporting.Ui_ExportDialog()
|
self.frm = aqt.forms.exporting.Ui_ExportDialog()
|
||||||
self.frm.setupUi(self)
|
self.frm.setupUi(self)
|
||||||
self.exporter = None
|
self.exporter = None
|
||||||
|
self.cids = cids
|
||||||
self.setup(did)
|
self.setup(did)
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
|
||||||
def setup(self, did):
|
def setup(self, did: Optional[int]):
|
||||||
self.exporters = exporters()
|
self.exporters = exporters()
|
||||||
# if a deck specified, start with .apkg type selected
|
# if a deck specified, start with .apkg type selected
|
||||||
idx = 0
|
idx = 0
|
||||||
if did:
|
if did or self.cids:
|
||||||
for c, (k, e) in enumerate(self.exporters):
|
for c, (k, e) in enumerate(self.exporters):
|
||||||
if e.ext == ".apkg":
|
if e.ext == ".apkg":
|
||||||
idx = c
|
idx = c
|
||||||
|
@ -38,7 +40,10 @@ class ExportDialog(QDialog):
|
||||||
self.frm.format.activated.connect(self.exporterChanged)
|
self.frm.format.activated.connect(self.exporterChanged)
|
||||||
self.exporterChanged(idx)
|
self.exporterChanged(idx)
|
||||||
# deck list
|
# 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)
|
self.frm.deck.addItems(self.decks)
|
||||||
# save button
|
# save button
|
||||||
b = QPushButton(_("Export..."))
|
b = QPushButton(_("Export..."))
|
||||||
|
@ -77,9 +82,18 @@ class ExportDialog(QDialog):
|
||||||
self.exporter.includeMedia = self.frm.includeMedia.isChecked()
|
self.exporter.includeMedia = self.frm.includeMedia.isChecked()
|
||||||
self.exporter.includeTags = self.frm.includeTags.isChecked()
|
self.exporter.includeTags = self.frm.includeTags.isChecked()
|
||||||
self.exporter.includeHTML = self.frm.includeHTML.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
|
self.exporter.did = None
|
||||||
|
elif idx == 0:
|
||||||
|
# All decks
|
||||||
|
self.exporter.did = None
|
||||||
|
self.exporter.cids = None
|
||||||
else:
|
else:
|
||||||
|
# Deck idx-1 in the list of decks
|
||||||
|
self.exporter.cids = None
|
||||||
name = self.decks[self.frm.deck.currentIndex()]
|
name = self.decks[self.frm.deck.currentIndex()]
|
||||||
self.exporter.did = self.col.decks.id(name)
|
self.exporter.did = self.col.decks.id(name)
|
||||||
if self.isVerbatim:
|
if self.isVerbatim:
|
||||||
|
|
|
@ -295,6 +295,7 @@
|
||||||
<addaction name="menuFlag"/>
|
<addaction name="menuFlag"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Info"/>
|
<addaction name="action_Info"/>
|
||||||
|
<addaction name="actionExport"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_Notes">
|
<widget class="QMenu" name="menu_Notes">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -599,6 +600,14 @@
|
||||||
<string notr="true">Ctrl+K</string>
|
<string notr="true">Ctrl+K</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionExport">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Export Notes</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+Shift+E</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="icons.qrc"/>
|
<include location="icons.qrc"/>
|
||||||
|
|
Loading…
Reference in a new issue