Skip to content
This repository has been archived by the owner on Jan 16, 2023. It is now read-only.

Merge in JPincock current #1

Open
wants to merge 50 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
c546eb8
update fix - thanks andrewsanchez
johnpincock Aug 16, 2020
8f3b26e
Add note type mapping functionality
hgiesel Nov 25, 2020
6599c6e
Use note type mapping functionality in _importNoteTypes
hgiesel Nov 25, 2020
38354ed
Refactoring and Whitespace
hgiesel Nov 25, 2020
ed4fda5
Reformat + One use note type mapping if UpdateNoteTypeStyling is checked
hgiesel Nov 27, 2020
8c66cb9
Merge pull request #21 from hgiesel/notetypemapping
johnpincock Nov 29, 2020
3144d72
Move the check for special fields after calling _uniquifyNotes
hgiesel Nov 30, 2020
3b52ff4
Merge pull request #22 from hgiesel/mappingfix
johnpincock Dec 3, 2020
b3997c3
Correctly update media references when importing with a note type map…
hgiesel Jan 11, 2021
5b99178
Merge pull request #23 from hgiesel/mediafix
johnpincock Jan 12, 2021
2001a72
Introduce keep tags feature
hgiesel Jan 18, 2021
fe07e4d
Update manifest with package ID and version
AnKingMed Jan 18, 2021
191a8f7
Merge pull request #6 from johnpincock/master
AnKingMed Jan 18, 2021
c7d7f1b
Update dialog.py
AnKingMed Jan 19, 2021
96a5e31
Merge pull request #24 from hgiesel/keeptags
johnpincock Jan 19, 2021
e94afee
Merge pull request #25 from AnKingMed/master
johnpincock Jan 19, 2021
0aafc4b
Make the keep tag text identifier at top
AnKingMed Jan 19, 2021
72f3133
Merge pull request #7 from johnpincock/master
AnKingMed Jan 20, 2021
da68794
Add QLineEdit
AnKingMed Jan 20, 2021
5fe374d
Make Qlineedit longer
AnKingMed Jan 20, 2021
5d6fd20
Small stability checks by Henrik
AnKingMed Jan 21, 2021
8be1bbf
Set config defaults
AnKingMed Jan 21, 2021
338f944
Merge pull request #26 from AnKingMed/QLineEdit
AnKingMed Jan 22, 2021
ab872f9
Merge pull request #8 from johnpincock/master
AnKingMed Feb 9, 2021
2dd7658
Update special fields video link
AnKingMed Feb 9, 2021
1532232
Update manifest.json
AnKingMed Feb 9, 2021
84f5a9d
Merge pull request #27 from AnKingMed/master
AnKingMed Feb 9, 2021
eb3d1fb
Keep marked and leech tags when updating tags
AnKingMed Feb 13, 2021
6f334f6
Update version
AnKingMed Feb 13, 2021
ce18719
specify widget positions on the grid
BlueGreenMagick Jun 20, 2021
9435d74
programatically remove initial widgets from grid
BlueGreenMagick Jun 20, 2021
9c30ca2
Merge pull request #29 from BlueGreenMagick/master
AnKingMed Jun 20, 2021
3110964
Update version
AnKingMed Jun 20, 2021
800284f
Update for Anki 2.1.50
RisingOrange Dec 31, 2021
2a69c3a
Add old intTime definition
RisingOrange Dec 31, 2021
35f4d25
Merge pull request #31 from RisingOrange/master
AnKingMed Jan 16, 2022
5a3540f
Update version
AnKingMed Jan 16, 2022
a8c6233
Fix Passes invalid note ids to `models.change()` #30
RisingOrange Feb 23, 2022
4128bb0
Merge branch 'johnpincock:master' into master
RisingOrange Feb 23, 2022
fe1dcbf
Merge pull request #32 from RisingOrange/master
AnKingMed Feb 23, 2022
0096d21
Disable the new APKG importer
abdnh Nov 17, 2022
77023f9
Merge pull request #33 from abdnh/new-importer
AnKingMed Nov 20, 2022
0a882af
Use scoped Qt enums
abdnh Oct 31, 2023
e813074
Merge pull request #36 from abdnh/qt6
AnKingMed Nov 1, 2023
eb9d31d
Stop disabling new APKG importer
abdnh Mar 16, 2024
dd9ea1a
Offer to enable legacy importer/exporter
abdnh Mar 16, 2024
357d14a
Add sentence about importing new files
abdnh Mar 18, 2024
13a6ae2
Merge pull request #38 from abdnh/do-not-override-new-importer
AnKingMed Mar 19, 2024
e1d41c2
Prompt to do a legacy import dynamically
abdnh Oct 26, 2024
cf288ab
Merge pull request #39 from abdnh/dynamic-legacy-import
AnKingMed Oct 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 111 additions & 30 deletions Specialfields21/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import time

from anki.hooks import schema_will_change
from anki.importing import Anki2Importer
from anki.importing.anki2 import Anki2Importer
from anki.lang import _
from anki.utils import json
from aqt import mw
from aqt.utils import showWarning

from . import dialog
from .config import getUserOption
from .dialog import returnTagsText
from .note_type_mapping import create_mapping_on_field_name_equality

# #########################################################
#
# See this video for how to use this add-on: https://youtu.be/cg-tQ6Ut0IQ
#
# #########################################################

NID = 0
GUID = 1
MID = 2
MOD = 3
Expand All @@ -30,7 +34,7 @@ def getUserOptionSpecial(key=None, default=None):
return default


def newImportNotes(self) -> None:
def newImportNotes(self: Anki2Importer) -> None:
# build guid -> (id,mod,mid) hash & map of existing note ids
self._notes = {}
existing = {}
Expand All @@ -54,16 +58,10 @@ def newImportNotes(self) -> None:
dupesIdentical = []
dupesIgnored = []
total = 0
########################################################################
# check if any models with special field exist
midCheck = []
a = mw.col.models.all()
for i in a:
fields = i["flds"]
for n in fields:
if n['name'] in getUserOptionSpecial("Special field", []) or getUserOptionSpecial("All fields are special", False):
midCheck.append(str(i["id"]))
########################################################################

######### note type mapping
schema_will_change.remove(mw.onSchemaMod)
######### /note type mapping

for note in self.src.db.execute("select * from notes"):
total += 1
Expand All @@ -89,7 +87,10 @@ def newImportNotes(self) -> None:
if self.allowUpdate:
oldNid, oldMod, oldMid = self._notes[note[GUID]]
# will update if incoming note more recent
if oldMod < note[MOD] or (not getUserOptionSpecial("update only if newer", True)):

if oldMod < note[MOD] or (
not getUserOptionSpecial("update only if newer", True)
):
# safe if note types identical
if oldMid == note[MID]:
# incoming note should use existing id
Expand All @@ -99,16 +100,60 @@ def newImportNotes(self) -> None:
update.append(note)
dirty.append(note[0])
else:
dupesIgnored.append(note)
self._ignoredGuids[note[GUID]] = True
######### note type mapping
updateNoteType = getUserOptionSpecial("update note styling")

old_model = self.dst.models.get(oldMid)
target_model = self.dst.models.get(note[MID])

mapping = create_mapping_on_field_name_equality(
old_model, target_model
)

if updateNoteType and mapping:
self.dst.models.change(
old_model,
[oldNid],
target_model,
mapping.get_field_map(),
mapping.get_card_type_map(),
)

note[0] = oldNid
note[4] = usn
note[6] = self._mungeMedia(note[MID], note[6])
update.append(note)
dirty.append(note[0])

######### /note type mapping
else:
dupesIgnored.append(note)
self._ignoredGuids[note[GUID]] = True
else:
dupesIdentical.append(note)

self.log.append(_("Notes found in file: %d") % total)

######### note type mapping
schema_will_change.append(mw.onSchemaMod)
######### /note type mapping

########################################################################
# check if any models with special field exist
midCheck = []
a = mw.col.models.all()
for i in a:
fields = i["flds"]
for n in fields:
if n["name"] in getUserOptionSpecial(
"Special field", []
) or getUserOptionSpecial("All fields are special", False):
midCheck.append(str(i["id"]))
########################################################################

for note in update:
oldnote = mw.col.getNote(note[0])
newTags = [t for t in note[5].replace('\u3000', ' ').split(" ") if t]
newTags = [t for t in note[5].replace("\u3000", " ").split(" ") if t]
for tag in oldnote.tags:
for i in newTags:
if i.lower() == tag.lower():
Expand All @@ -117,12 +162,31 @@ def newImportNotes(self) -> None:

newTags = set(newTags)
togetherTags = " %s " % " ".join(newTags)

######### KEEP tags
keepTags = [t for t in note[5].replace("\u3000", " ").split(" ") if t]
for tag in oldnote.tags:
for i in keepTags:
if i.lower() == tag.lower():
tag = i

for item in returnTagsText():
if item in tag:
keepTags.append(tag)

if "marked" in tag or "leech" in tag:
keepTags.append(tag)

keepTags = set(keepTags)
keepTagsTogether = " %s " % " ".join(keepTags)
######### /KEEP tags

mid = str(note[2])
if mid in midCheck:
model = mw.col.models.get(mid)
specialFields = getUserOptionSpecial("Special field", [])
if getUserOptionSpecial("All fields are special", False):
specialFields = [fld['name'] for fld in model['flds']]
specialFields = [fld["name"] for fld in model["flds"]]
# if this note belongs to a model with "Special Field"
trow = list(note)
for i in specialFields:
Expand All @@ -136,41 +200,46 @@ def newImportNotes(self) -> None:
# valueLocal = mw.col.getNote(note[0]).values()
# splitRow[indexOfField] = valueLocal[indexOfField]

finalrow = ''
finalrow = ""
count = 0
for a in splitRow:
if count == fieldOrd:
finalrow += str(fields[fieldOrd]) + "\x1f"
else:
finalrow += a+"\x1f"
finalrow += a + "\x1f"
count = count + 1

def rreplace(s, old, new, occurrence):
li = s.rsplit(old, occurrence)
return new.join(li)
finarow = rreplace(finalrow, """\x1f""", '', 1)

finarow = rreplace(finalrow, """\x1f""", "", 1)
note[6] = str(finarow)
# if note[0] == 1558556384609: #FOR TROUBLE SHOOTING ! Change to the card.id you are uncertain about

except:
pass
if getUserOptionSpecial("Combine tagging", False):
note[5] = togetherTags
else:
note[5] = keepTagsTogether

self.log.append(_("Notes found in file: %d") % total)

if dupesIgnored:
self.log.append(
_("Notes that could not be imported as note type has changed: %d")
% len(dupesIgnored))
% len(dupesIgnored)
)
if update:
self.log.append(
_("Notes updated, as file had newer version: %d") % len(update))
self.log.append(_("Notes updated, as file had newer version: %d") % len(update))
if add:
self.log.append(_("Notes added from file: %d") % len(add))
if dupesIdentical:
self.log.append(_("Notes skipped, as they're already in your collection: %d") %
len(dupesIdentical))
self.log.append(
_("Notes skipped, as they're already in your collection: %d")
% len(dupesIdentical)
)

self.log.append("")

Expand Down Expand Up @@ -207,7 +276,7 @@ def rreplace(s, old, new, occurrence):
for importedDid, importedDeck in ((d["id"], d) for d in self.src.decks.all()):
localDid = self._did(importedDid)
localDeck = self.dst.decks.get(localDid)
localDeck['desc'] = importedDeck['desc']
localDeck["desc"] = importedDeck["desc"]
self.dst.decks.save(localDeck)


Expand Down Expand Up @@ -248,8 +317,11 @@ def _mid(self, srcMid):
dstScm = self.dst.models.scmhash(dstModel)
if srcScm == dstScm:
# copy styling changes over if newer
if updateNoteType or (updateNoteType is None and srcModel["mod"] > dstModel["mod"]):
if updateNoteType or (
updateNoteType is None and srcModel["mod"] > dstModel["mod"]
):
model = srcModel.copy()
model["mod"] = max(srcModel["mod"], dstModel["mod"])
model["id"] = mid
model["usn"] = self.col.usn()
self.dst.models.update(model)
Expand All @@ -263,6 +335,7 @@ def _mid(self, srcMid):

Anki2Importer._mid = _mid


def _did(self, did: int):
"Given did in src col, return local id."
# already converted?
Expand All @@ -287,7 +360,7 @@ def _did(self, did: int):
self._did(idInSrc)
# if target is a filtered deck, we'll need a new deck name
deck = self.dst.decks.byName(name)

is_new = not bool(deck)

if deck and deck["dyn"]:
Expand All @@ -311,4 +384,12 @@ def _did(self, did: int):
# add to deck map and return
self._decks[did] = newid
return newid


def intTime(scale: int = 1) -> int:
# copied from aqt.utils of Anki versions < 2.1.50
"The time in integer seconds. Pass scale=1000 to get milliseconds."
return int(time.time() * scale)


Anki2Importer._did = _did
2 changes: 2 additions & 0 deletions Specialfields21/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{"current config": {
"All fields are special": true,
"Combine tagging": true,
"Protected tags": ["%%keep%%"],
"Special field":
["Lecture Notes", "Missed Questions", "Pathoma", "Boards and Beyond"],
"update deck description": false,
Expand All @@ -11,6 +12,7 @@
"user default config": {
"All fields are special": true,
"Combine tagging": true,
"Protected tags": ["%%keep%%"],
"Special field":
["Lecture Notes", "Missed Questions", "Pathoma", "Boards and Beyond"],
"update deck description": false,
Expand Down
3 changes: 0 additions & 3 deletions Specialfields21/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import sys

from aqt import mw
from aqt.utils import showWarning

userOption = None

Expand Down
Loading