From b78480fe5282fd54ed56b98252e197cfc2aaff10 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Wed, 23 Oct 2019 03:44:44 +0200 Subject: [PATCH 1/2] New model can be edited without full sync This commit solves a problem that I had many time in the past. When I create a new model, I usually want to edit it. Clone of existing models present no interest by themselves. And as soon as I edit it, I need to do a full sync. As far as I understand ankiweb (which is sadly closed source), the full sync is required because ankiweb needs to know that the model associated to note type on the server did change. But since the model is new, it has no note type associated to on the server, so there is no need to do a full sync immediatly. Since the model is new, it also means there is no risk of the inconsistency with a change made in another computer/smartphone. Thus, when a field/template is added, I check that the model is not new by checking both whether it's id is not null, and also that it's usn is not -1. (I set usn early in the model's life) If it does not make into anki, then it'll be an add-on. But it's worth a try first. --- anki/models.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/anki/models.py b/anki/models.py index d37b7e24e..f9ebd997b 100644 --- a/anki/models.py +++ b/anki/models.py @@ -150,6 +150,7 @@ class ModelManager: m['tmpls'] = [] m['tags'] = [] m['id'] = None + m['usn'] = self.col.usn() return m def rem(self, m): @@ -225,6 +226,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) m2 = copy.deepcopy(m) m2['name'] = _("%s copy") % m2['name'] self.add(m2) + m['usn'] = self.col.usn() return m2 # Fields @@ -253,9 +255,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) self.save(m) def addField(self, m, field): - # only mod schema if model isn't new - if m['id']: - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) m['flds'].append(field) self._updateFieldOrds(m) self.save(m) @@ -352,8 +352,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) def addTemplate(self, m, template): "Note: should col.genCards() afterwards." - if m['id']: - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) m['tmpls'].append(template) self._updateTemplOrds(m) self.save(m) @@ -474,6 +473,10 @@ select id from notes where mid = ?)""" % " ".join(map), d) self.col.remCards(deleted) + def _modSchemaIfRequired(self, m): + if m['id'] and m["usn"] != -1: + self.col.modSchema(check=True) + # Schema hash ########################################################################## From 9863b6f9ff2d75763bcc055395a35a8cb1f43a19 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Wed, 23 Oct 2019 04:48:14 +0200 Subject: [PATCH 2/2] Use _modSchemaIfRequired in all cases. Same logic than in last commit. Actually, there is no change of model which need a full sync until the model is uploaded. After all, even if a change in model imply that some card will change, those cards and notes have not been uploaded either --- anki/models.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/anki/models.py b/anki/models.py index f9ebd997b..4238613ab 100644 --- a/anki/models.py +++ b/anki/models.py @@ -155,7 +155,7 @@ class ModelManager: def rem(self, m): "Delete model, and all its cards/notes." - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) current = self.current()['id'] == m['id'] # delete notes/cards self.col.remCards(self.col.db.list(""" @@ -249,7 +249,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) def setSortIdx(self, m, idx): assert 0 <= idx < len(m['flds']) - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) m['sortf'] = idx self.col.updateFieldCache(self.nids(m)) self.save(m) @@ -265,7 +265,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) self._transformFields(m, add) def remField(self, m, field): - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) # save old sort field sortFldName = m['flds'][m['sortf']]['name'] idx = m['flds'].index(field) @@ -288,7 +288,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) self.renameField(m, field, None) def moveField(self, m, field, idx): - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) oldidx = m['flds'].index(field) if oldidx == idx: return @@ -309,7 +309,7 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) self._transformFields(m, move) def renameField(self, m, field, newName): - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) pat = r'{{([^{}]*)([:#^/]|[^:#/^}][^:}]*?:|)%s}}' def wrap(txt): def repl(match): @@ -375,7 +375,7 @@ having count() < 2 limit 1""" % ids2str(cids)): return False # ok to proceed; remove cards - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) self.col.remCards(cids) # shift ordinals self.col.db.execute(""" @@ -419,7 +419,7 @@ select id from notes where mid = ?)""" % " ".join(map), # - newModel should be self if model is not changing def change(self, m, nids, newModel, fmap, cmap): - self.col.modSchema(check=True) + self._modSchemaIfRequired(m) assert newModel['id'] == m['id'] or (fmap and cmap) if fmap: self._changeNotes(nids, newModel, fmap)