diff --git a/anki/decks.py b/anki/decks.py index b7940abda..b939bd5e8 100644 --- a/anki/decks.py +++ b/anki/decks.py @@ -233,6 +233,11 @@ class DeckManager(object): raise DeckRenameError(_("That deck already exists.")) # ensure we have parents newName = self._ensureParents(newName) + # make sure we're not nesting under a filtered deck + if '::' in newName: + newParent = '::'.join(newName.split('::')[:-1]) + if self.byName(newParent)['dyn']: + raise DeckRenameError(_("A filtered deck cannot have subdecks.")) # rename children for grp in self.all(): if grp['name'].startswith(g['name'] + "::"): @@ -266,8 +271,6 @@ class DeckManager(object): or self._isParent(ontoDeckName, draggedDeckName) \ or self._isAncestor(draggedDeckName, ontoDeckName): return False - elif self.byName(ontoDeckName)['dyn']: - raise DeckRenameError(_("A filtered deck cannot have subdecks.")) else: return True diff --git a/anki/models.py b/anki/models.py index 5249ee128..7f46b524b 100644 --- a/anki/models.py +++ b/anki/models.py @@ -304,10 +304,10 @@ and notes.mid = ? and cards.ord = ?""", m['id'], ord) def renameField(self, m, field, newName): self.col.modSchema() - pat = r'{{([:#^/]|[^:#/^}][^:}]*?:|)%s}}' + pat = r'{{(.*)([:#^/]|[^:#/^}][^:}]*?:|)%s}}' def wrap(txt): def repl(match): - return '{{' + match.group(1) + txt + '}}' + return '{{' + match.group(1) + match.group(2) + txt + '}}' return repl for t in m['tmpls']: for fmt in ('qfmt', 'afmt'): diff --git a/anki/tags.py b/anki/tags.py index aff74082e..e752fdb7c 100644 --- a/anki/tags.py +++ b/anki/tags.py @@ -109,7 +109,7 @@ class TagManager(object): def split(self, tags): "Parse a string and return a list of tags." - return [t for t in tags.split(" ") if t] + return [t for t in tags.replace(u'\u3000', ' ').split(" ") if t] def join(self, tags): "Join tags into a single string, with leading and trailing spaces." diff --git a/aqt/about.py b/aqt/about.py index 21a6e6004..650695d47 100644 --- a/aqt/about.py +++ b/aqt/about.py @@ -28,7 +28,7 @@ system. It's free and open source.") "" abouttext += '

' + _("Written by Damien Elmes, with patches, translation,\ testing and design from:

%(cont)s") % {'cont': u"""Aaron Harsh, Ádám Szegi, -Alex Fraser, Andreas Klauer, Andrew Wright, Bernhard Ibertsberger, Charlene Barina, +Alex Fraser, Andreas Klauer, Andrew Wright, Bernhard Ibertsberger, C. van Rooyen, Charlene Barina, Christian Krause, Christian Rusche, David Smith, Dave Druelinger, Dotan Cohen, Emilio Wuerges, Emmanuel Jarri, Frank Harper, Gregor Skumavc, H. Mijail, Houssam Salem, Ian Lewis, Immanuel Asmus, Iroiro, Jarvik7, diff --git a/aqt/browser.py b/aqt/browser.py index 340547865..be35a8ff7 100644 --- a/aqt/browser.py +++ b/aqt/browser.py @@ -1109,12 +1109,26 @@ where id in %s""" % ids2str(sf)) return self.mw.checkpoint(_("Delete Notes")) self.model.beginReset() - oldRow = self.form.tableView.selectionModel().currentIndex().row() + # figure out where to place the cursor after the deletion + curRow = self.form.tableView.selectionModel().currentIndex().row() + selectedRows = [i.row() for i in + self.form.tableView.selectionModel().selectedRows()] + if min(selectedRows) < curRow < max(selectedRows): + # last selection in middle; place one below last selected item + move = sum(1 for i in selectedRows if i > curRow) + newRow = curRow - move + elif max(selectedRows) <= curRow: + # last selection at bottom; place one below bottommost selection + newRow = max(selectedRows) - len(nids) + 1 + else: + # last selection at top; place one above topmost selection + newRow = min(selectedRows) - 1 self.col.remNotes(nids) self.onSearch(reset=False) if len(self.model.cards): - new = min(oldRow, len(self.model.cards) - 1) - self.model.focusedCard = self.model.cards[new] + newRow = min(newRow, len(self.model.cards) - 1) + newRow = max(newRow, 0) + self.model.focusedCard = self.model.cards[newRow] self.model.endReset() self.mw.requireReset() tooltip(_("%s deleted.") % (ngettext("%d note", "%d notes", len(nids)) % len(nids))) diff --git a/aqt/clayout.py b/aqt/clayout.py index aa5f423e6..fd2eba116 100644 --- a/aqt/clayout.py +++ b/aqt/clayout.py @@ -204,6 +204,12 @@ Please create a new card type first.""")) self.tab['tform'].front.setPlainText(t['qfmt']) self.tab['tform'].css.setPlainText(self.model['css']) self.tab['tform'].back.setPlainText(t['afmt']) + self.tab['tform'].front.setAcceptRichText(False) + self.tab['tform'].css.setAcceptRichText(False) + self.tab['tform'].back.setAcceptRichText(False) + self.tab['tform'].front.setTabStopWidth(30) + self.tab['tform'].css.setTabStopWidth(30) + self.tab['tform'].back.setTabStopWidth(30) self.redrawing = False def saveCard(self): diff --git a/aqt/exporting.py b/aqt/exporting.py index bc373b077..3d80266b4 100644 --- a/aqt/exporting.py +++ b/aqt/exporting.py @@ -64,13 +64,20 @@ class ExportDialog(QDialog): self.exporter.did): verbatim = True # it's a verbatim apkg export, so place on desktop instead of - # choosing file + # choosing file; use homedir if no desktop + usingHomedir = False file = os.path.join(QDesktopServices.storageLocation( QDesktopServices.DesktopLocation), "collection.apkg") + if not os.path.exists(os.path.dirname(file)): + usingHomedir = True + file = os.path.join(QDesktopServices.storageLocation( + QDesktopServices.HomeLocation), "collection.apkg") if os.path.exists(file): - if not askUser( - _("%s already exists on your desktop. Overwrite it?")% - "collection.apkg"): + if usingHomedir: + question = _("%s already exists in your home directory. Overwrite it?") + else: + question = _("%s already exists on your desktop. Overwrite it?") + if not askUser(question % "collection.apkg"): return else: verbatim = False @@ -100,7 +107,11 @@ class ExportDialog(QDialog): os.unlink(file) self.exporter.exportInto(file) if verbatim: - msg = _("A file called collection.apkg was saved on your desktop.") + if usingHomedir: + msg = _("A file called %s was saved in your home directory.") + else: + msg = _("A file called %s was saved on your desktop.") + msg = msg % "collection.apkg" period = 5000 else: period = 3000 diff --git a/aqt/importing.py b/aqt/importing.py index e3a42a82c..ae0130a50 100644 --- a/aqt/importing.py +++ b/aqt/importing.py @@ -34,7 +34,7 @@ class ChangeMap(QDialog): self.frm.fields.setCurrentRow(n) n += 1 self.frm.fields.addItem(QListWidgetItem(_("Map to Tags"))) - self.frm.fields.addItem(QListWidgetItem(_("Discard field"))) + self.frm.fields.addItem(QListWidgetItem(_("Ignore field"))) if not setCurrent: if current == "_tags": self.frm.fields.setCurrentRow(n) diff --git a/designer/main.ui b/designer/main.ui index 04f802dc1..9b9615e5c 100644 --- a/designer/main.ui +++ b/designer/main.ui @@ -46,7 +46,7 @@ 0 0 412 - 22 + 27 @@ -237,6 +237,9 @@ Manage Note Types... + + Ctrl+Shift+N +