From accbc53e5d961d6a90cec1b0695e8bdb1b437142 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Thu, 13 Apr 2023 19:30:49 -0600 Subject: [PATCH 1/3] added modelTemplateRename, modelTemplateReposition, modelTemplateAdd, modelTemplateRemove --- README.md | 130 ++++++++++++++++++++++++++++++++++++++++++- plugin/__init__.py | 79 ++++++++++++++++++++++---- tests/test_models.py | 56 +++++++++++++++++++ 3 files changed, 254 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 585e9ff..52c9adc 100644 --- a/README.md +++ b/README.md @@ -2630,6 +2630,134 @@ corresponding to when the API was available for use. ``` +#### `modelTemplateRename` + +* Renames a template in an existing model. + +
+ Sample request: + + ```json + { + "action": "modelTemplateRename", + "version": 6, + "params": { + "modelName": "Basic", + "oldTemplateName": "Card 1", + "newTemplateName": "Card 1 renamed" + } + } + ``` +
+ +
+ Sample result: + + ```json + { + "result": null, + "error": null + } + ``` +
+ +#### `modelTemplateReposition` + +* Repositions a template in an existing model. + + The value of `index` starts at 0. For example, an index of `0` puts the template in the first position, and an index of `2` puts the template in the third position. + +
+ Sample request: + + ```json + { + "action": "modelTemplateRemove", + "version": 6, + "params": { + "modelName": "Basic", + "templateName": "Card 1", + "index": 1 + } + } + ``` +
+ +
+ Sample result: + + ```json + { + "result": null, + "error": null + } + ``` +
+ +#### `modelTemplateAdd` + +* Adds a template to an existing model by name. If you want to update an existing template, use `updateModelTemplates`. + +
+ Sample request: + + ```json + { + "action": "modelTemplateAdd", + "version": 6, + "params": { + "modelName": "Basic", + "template": { + "Name": "Card 3", + "Front": "Front html {{Field1}}", + "Back": "Back html {{Field2}}" + } + } + } + ``` +
+ +
+ Sample result: + + ```json + { + "result": null, + "error": null + } + ``` +
+ +#### `modelTemplateRemove` + +* Removes a template from an existing model. + +
+ Sample request: + + ```json + { + "action": "modelTemplateRemove", + "version": 6, + "params": { + "modelName": "Basic", + "templateName": "Card 1" + } + } + ``` +
+ +
+ Sample result: + + ```json + { + "result": null, + "error": null + } + ``` +
+ #### `modelFieldRename` * Rename the field name of a given model. @@ -2644,7 +2772,7 @@ corresponding to when the API was available for use. "params": { "modelName": "Basic", "oldFieldName": "Front", - "newFieldName": "FrontRenamed" + "newFieldName": "Front2" } } ``` diff --git a/plugin/__init__.py b/plugin/__init__.py index eaefc32..a30fca0 100644 --- a/plugin/__init__.py +++ b/plugin/__init__.py @@ -196,15 +196,20 @@ class AnkiConnect: return model - def getField(self, modelName, fieldName): - model = self.getModel(modelName) - + def getField(self, model, fieldName): fieldMap = self.collection().models.fieldMap(model) if fieldName not in fieldMap: - raise Exception('field was not found in {}: {}'.format(modelName, fieldName)) + raise Exception('field was not found in {}: {}'.format(model['name'], fieldName)) return fieldMap[fieldName][1] + def getTemplate(self, model, templateName): + for ankiTemplate in model['tmpls']: + if ankiTemplate['name'] == templateName: + return ankiTemplate + raise Exception('template was not found in {}: {}'.format(model['name'], templateName)) + + def startEditing(self): self.window().requireReset() @@ -1268,11 +1273,65 @@ class AnkiConnect: return updatedModels + @util.api() + def modelTemplateRename(self, modelName, oldTemplateName, newTemplateName): + mm = self.collection().models + model = self.getModel(modelName) + ankiTemplate = self.getTemplate(model, oldTemplateName) + + ankiTemplate['name'] = newTemplateName + self.save_model(mm, model) + + + @util.api() + def modelTemplateReposition(self, modelName, templateName, index): + mm = self.collection().models + model = self.getModel(modelName) + ankiTemplate = self.getTemplate(model, templateName) + + mm.reposition_template(model, ankiTemplate, index) + self.save_model(mm, model) + + + @util.api() + def modelTemplateAdd(self, modelName, template): + # "Name", "Front", "Back" borrows from `createModel` + mm = self.collection().models + model = self.getModel(modelName) + name = template['Name'] + qfmt = template['Front'] + afmt = template['Back'] + + # updates the template if it already exists + for ankiTemplate in model['tmpls']: + if ankiTemplate['name'] == name: + ankiTemplate['qfmt'] = qfmt + ankiTemplate['afmt'] = afmt + return + + ankiTemplate = mm.new_template(name) + ankiTemplate['qfmt'] = qfmt + ankiTemplate['afmt'] = afmt + mm.add_template(model, ankiTemplate) + + self.save_model(mm, model) + + + @util.api() + def modelTemplateRemove(self, modelName, templateName): + mm = self.collection().models + model = self.getModel(modelName) + ankiTemplate = self.getTemplate(model, templateName) + + mm.remove_template(model, ankiTemplate) + self.save_model(mm, model) + + @util.api() def modelFieldRename(self, modelName, oldFieldName, newFieldName): mm = self.collection().models model = self.getModel(modelName) - field = self.getField(modelName, oldFieldName) + field = self.getField(model, oldFieldName) mm.renameField(model, field, newFieldName) @@ -1283,7 +1342,7 @@ class AnkiConnect: def modelFieldReposition(self, modelName, fieldName, index): mm = self.collection().models model = self.getModel(modelName) - field = self.getField(modelName, fieldName) + field = self.getField(model, fieldName) mm.repositionField(model, field, index) @@ -1314,7 +1373,7 @@ class AnkiConnect: def modelFieldRemove(self, modelName, fieldName): mm = self.collection().models model = self.getModel(modelName) - field = self.getField(modelName, fieldName) + field = self.getField(model, fieldName) mm.removeField(model, field) @@ -1325,7 +1384,7 @@ class AnkiConnect: def modelFieldSetFont(self, modelName, fieldName, font): mm = self.collection().models model = self.getModel(modelName) - field = self.getField(modelName, fieldName) + field = self.getField(model, fieldName) if not isinstance(font, str): raise Exception('font should be a string: {}'.format(font)) @@ -1339,7 +1398,7 @@ class AnkiConnect: def modelFieldSetFontSize(self, modelName, fieldName, fontSize): mm = self.collection().models model = self.getModel(modelName) - field = self.getField(modelName, fieldName) + field = self.getField(model, fieldName) if not isinstance(fontSize, int): raise Exception('fontSize should be an integer: {}'.format(fontSize)) @@ -1353,7 +1412,7 @@ class AnkiConnect: def modelFieldSetDescription(self, modelName, fieldName, description): mm = self.collection().models model = self.getModel(modelName) - field = self.getField(modelName, fieldName) + field = self.getField(model, fieldName) if not isinstance(description, str): raise Exception('description should be a string: {}'.format(description)) diff --git a/tests/test_models.py b/tests/test_models.py index bf8aa97..c3db38e 100755 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -132,6 +132,62 @@ def test_findAndReplaceInModels(setup): } +class TestModelTemplates: + def test_modelTemplateRename(self, setup): + ac.modelTemplateRename( + modelName="test_model", + oldTemplateName="Card 1", + newTemplateName="Card 1 Renamed", + ) + + result = ac.modelTemplates(modelName="test_model") + assert result == { + "Card 1 Renamed": {"Front": "{{field1}}", "Back": "{{field2}}"}, + "Card 2": {"Front": "{{field2}}", "Back": "{{field1}}"} + } + + def test_modelTemplateReposition(self, setup): + # There currently isn't a way to test for order, so this is just a + # smoke test for now + ac.modelTemplateReposition( + modelName="test_model", + templateName="Card 1", + index=1, + ) + + def test_modelTemplateAdd(self, setup): + # There currently isn't a way to test for order, so this is just a + # smoke test for now + ac.modelTemplateAdd( + modelName="test_model", + template={ + "Name": "Card 3", + "Front": "{{field1}} Card 3", + "Back": "{{field2}}", + } + ) + + result = ac.modelTemplates(modelName="test_model") + assert result == { + "Card 1": {"Front": "{{field1}}", "Back": "{{field2}}"}, + "Card 2": {"Front": "{{field2}}", "Back": "{{field1}}"}, + "Card 3": {"Front": "{{field1}} Card 3", "Back": "{{field2}}"}, + } + + def test_modelTemplateRemove(self, setup): + # There currently isn't a way to test for order, so this is just a + # smoke test for now + ac.modelTemplateRemove( + modelName="test_model", + templateName="Card 2" + ) + + result = ac.modelTemplates(modelName="test_model") + assert result == { + "Card 1": {"Front": "{{field1}}", "Back": "{{field2}}"}, + } + + class TestModelFieldNames: def test_modelFieldRename(self, setup): ac.modelFieldRename( From 918d4de72abb46a704e304e050237c52a0fdd021 Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Thu, 13 Apr 2023 20:33:18 -0600 Subject: [PATCH 2/3] fixed accidental change in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52c9adc..4785900 100644 --- a/README.md +++ b/README.md @@ -2772,7 +2772,7 @@ corresponding to when the API was available for use. "params": { "modelName": "Basic", "oldFieldName": "Front", - "newFieldName": "Front2" + "newFieldName": "FrontRenamed" } } ``` From fc63bdaa1753a099ca33da115146d8174c3c57eb Mon Sep 17 00:00:00 2001 From: Austin Siew <17107540+Aquafina-water-bottle@users.noreply.github.com> Date: Thu, 13 Apr 2023 20:36:07 -0600 Subject: [PATCH 3/3] removed unnecessary comments in test_models.py --- tests/test_models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index c3db38e..1cda36a 100755 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -156,8 +156,6 @@ class TestModelTemplates: ) def test_modelTemplateAdd(self, setup): - # There currently isn't a way to test for order, so this is just a - # smoke test for now ac.modelTemplateAdd( modelName="test_model", template={ @@ -175,8 +173,6 @@ class TestModelTemplates: } def test_modelTemplateRemove(self, setup): - # There currently isn't a way to test for order, so this is just a - # smoke test for now ac.modelTemplateRemove( modelName="test_model", templateName="Card 2"