diff --git a/aqt/browser.py b/aqt/browser.py index c9c8002ca..281668a9b 100644 --- a/aqt/browser.py +++ b/aqt/browser.py @@ -299,7 +299,7 @@ class StatusDelegate(QItemDelegate): class Browser(QMainWindow): def __init__(self, mw): - QMainWindow.__init__(self, None) + QMainWindow.__init__(self, mw) #applyStyles(self) self.mw = mw self.col = self.mw.col @@ -491,8 +491,8 @@ class Browser(QMainWindow): self.onRowChanged) def setupEditor(self): - self.editor = aqt.editor.Editor(self.mw, - self.form.fieldsArea) + self.editor = aqt.editor.Editor( + self.mw, self.form.fieldsArea, self) self.editor.stealFocus = False def onRowChanged(self, current, previous): @@ -534,7 +534,7 @@ class Browser(QMainWindow): def onSortChanged(self, idx, ord): type = self.model.activeCols[idx] - noSort = ("question", "answer", "template", "cardGroup", "noteGroup") + noSort = ("question", "answer", "template", "deck", "ndeck") if type in noSort: showInfo(_("Sorting on this column is not supported. Please " "choose another.")) diff --git a/aqt/clayout.py b/aqt/clayout.py index b207eb662..af5e0a48e 100644 --- a/aqt/clayout.py +++ b/aqt/clayout.py @@ -191,7 +191,7 @@ Please create a new card first.""")) n = len(self.cards) cur = self.card.template()['ord']+1 pos = getOnlyText( - _("Enter new card position (1..%s):") % n, + _("Enter new card position (1...%s):") % n, default=str(cur)) if not pos: return diff --git a/aqt/editor.py b/aqt/editor.py index 4caf0f2be..8f9665952 100644 --- a/aqt/editor.py +++ b/aqt/editor.py @@ -192,9 +192,10 @@ $(function () { # caller is responsible for resetting note on reset class Editor(object): - def __init__(self, mw, widget, addMode=False): - self.widget = widget + def __init__(self, mw, widget, parentWindow, addMode=False): self.mw = mw + self.widget = widget + self.parentWindow = parentWindow self.note = None self.stealFocus = True self.addMode = addMode @@ -233,7 +234,7 @@ class Editor(object): ###################################################################### def _addButton(self, name, func, key=None, tip=None, size=True, text="", - check=False): + check=False, native=False): b = QPushButton(text) if check: b.connect(b, SIGNAL("clicked(bool)"), func) @@ -242,7 +243,8 @@ class Editor(object): if size: b.setFixedHeight(20) b.setFixedWidth(20) - b.setStyle(self.plastiqueStyle) + if not native: + b.setStyle(self.plastiqueStyle) b.setFocusPolicy(Qt.NoFocus) if not text: b.setIcon(QIcon(":/icons/%s.png" % name)) @@ -266,13 +268,15 @@ class Editor(object): self.iconsBox.setMargin(0) self.iconsBox.setSpacing(0) self.outerLayout.addLayout(self.iconsBox) - # align to right - self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding)) b = self._addButton b("fields", self.onFields, "Ctrl+f", - shortcut(_("Layout (Ctrl+f)")), size=False, text=_("Fields")) + shortcut(_("Layout (Ctrl+f)")), size=False, text=_("Fields..."), + native=True) b("layout", self.onCardLayout, "Ctrl+l", - shortcut(_("Layout (Ctrl+l)")), size=False, text=_("Layout")) + shortcut(_("Layout (Ctrl+l)")), size=False, text=_("Layout..."), + native=True) + # align to right + self.iconsBox.addItem(QSpacerItem(20,1, QSizePolicy.Expanding)) b("text_bold", self.toggleBold, "Ctrl+b", _("Bold text (Ctrl+b)"), check=True) b("text_italic", self.toggleItalic, "Ctrl+i", _("Italic text (Ctrl+i)"), @@ -311,7 +315,7 @@ class Editor(object): def onFields(self): from aqt.fields import FieldDialog self.saveNow() - FieldDialog(self.mw, self.note, parent=self.widget) + FieldDialog(self.mw, self.note, parent=self.parentWindow) def onCardLayout(self): from aqt.clayout import CardLayout @@ -320,7 +324,7 @@ class Editor(object): ord = self.card.ord else: ord = 0 - CardLayout(self.mw, self.note, ord=ord, parent=self.widget) + CardLayout(self.mw, self.note, ord=ord, parent=self.parentWindow) self.loadNote() # JS->Python bridge diff --git a/aqt/fields.py b/aqt/fields.py index 7a19858f1..064d840a7 100644 --- a/aqt/fields.py +++ b/aqt/fields.py @@ -5,29 +5,25 @@ from aqt.qt import * import re from anki.consts import * import aqt -from aqt.utils import saveGeom, restoreGeom, getBase, mungeQA, \ - saveSplitter, restoreSplitter, showInfo, askUser, getText, \ - openHelp -from anki.utils import isMac, isWin - -# raise Exception("Remember to disallow media&latex refs in edit.") - -# need to strip the field management code out of this +from aqt.utils import showWarning, openHelp, getOnlyText class FieldDialog(QDialog): def __init__(self, mw, note, ord=0, parent=None): - QDialog.__init__(self, parent or mw, Qt.Window) + QDialog.__init__(self, parent or mw) #, Qt.Window) self.mw = aqt.mw self.parent = parent or mw self.note = note self.col = self.mw.col self.mm = self.mw.col.models self.model = note.model() + self.mw.checkpoint(_("Fields")) + self.setWindowModality(Qt.WindowModal) self.form = aqt.forms.fields.Ui_Dialog() self.form.setupUi(self) self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False) self.form.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False) + self.currentIdx = None self.fillFields() self.setupSignals() self.form.fieldList.setCurrentRow(0) @@ -36,6 +32,7 @@ class FieldDialog(QDialog): ########################################################################## def fillFields(self): + self.currentIdx = None self.form.fieldList.clear() for f in self.model['flds']: self.form.fieldList.addItem(f['name']) @@ -47,24 +44,80 @@ class FieldDialog(QDialog): c(f.fieldList, s("currentRowChanged(int)"), self.onRowChange) c(f.fieldAdd, s("clicked()"), self.onAdd) c(f.fieldDelete, s("clicked()"), self.onDelete) - c(f.fieldUp, s("clicked()"), self.onUp) - c(f.fieldDown, s("clicked()"), self.onDown) + c(f.fieldRename, s("clicked()"), self.onRename) + c(f.fieldPosition, s("clicked()"), self.onPosition) c(f.sortField, s("clicked()"), self.onSortField) + c(f.buttonBox, s("helpRequested()"), self.onHelp) def onRowChange(self, idx): + if idx == -1: + return + self.saveField() self.loadField(idx) + def _uniqueName(self, prompt, ignoreOrd=None): + txt = getOnlyText(prompt) + if not txt: + return + for f in self.model['flds']: + if ignoreOrd is not None and f['ord'] == ignoreOrd: + continue + if f['name'] == txt: + showWarning(_("That field name is already used.")) + return + return txt + + def onRename(self): + name = self._uniqueName(_("New name:"), self.currentIdx) + if not name: + return + idx = self.currentIdx + f = self.model['flds'][idx] + self.mm.renameField(self.model, f, name) + self.saveField() + self.fillFields() + self.form.fieldList.setCurrentRow(idx) + def onAdd(self): - pass + name = self._uniqueName(_("Field name:")) + if not name: + return + self.saveField() + self.mw.progress.start() + f = self.mm.newField(name) + self.mm.addField(self.model, f) + self.mw.progress.finish() + self.fillFields() + self.form.fieldList.setCurrentRow(len(self.model['flds'])-1) def onDelete(self): - pass + if len(self.model['flds']) < 3: + return showWarning(_("Notes require at least two fields.")) + f = self.model['flds'][self.form.fieldList.currentRow()] + self.mw.progress.start() + self.mm.remField(self.model, f) + self.mw.progress.finish() + self.fillFields() + self.form.fieldList.setCurrentRow(0) - def onUp(self): - pass - - def onDown(self): - pass + def onPosition(self, delta=-1): + l = len(self.model['flds']) + txt = getOnlyText(_("New position (1...%d):") % l) + if not txt: + return + try: + pos = int(txt) + except ValueError: + return + if not 0 < pos <= l: + return + self.saveField() + f = self.model['flds'][self.currentIdx] + self.mw.progress.start() + self.mm.moveField(self.model, f, pos-1) + self.mw.progress.finish() + self.fillFields() + self.form.fieldList.setCurrentRow(pos-1) def onSortField(self): # don't allow user to disable; it makes no sense @@ -72,389 +125,35 @@ class FieldDialog(QDialog): self.model['sortf'] = self.form.fieldList.currentRow() def loadField(self, idx): + self.currentIdx = idx fld = self.model['flds'][idx] f = self.form - f.fieldName.setText(fld['name']) f.fontFamily.setCurrentFont(QFont(fld['font'])) f.fontSize.setValue(fld['size']) f.sticky.setChecked(fld['sticky']) - print self.model['sortf'] == fld['ord'] f.sortField.setChecked(self.model['sortf'] == fld['ord']) f.rtl.setChecked(fld['rtl']) - # Cards & Preview - ########################################################################## - - def setupCards(self): - self.updatingCards = False - self.playedAudio = {} - f = self.form - if self.type == 0: - f.templateType.setText( - _("Templates that will be created:")) - elif self.type == 1: - f.templateType.setText( - _("Templates used by note:")) - else: - f.templateType.setText( - _("All templates:")) - # replace with more appropriate size hints - for e in ("cardQuestion", "cardAnswer"): - w = getattr(f, e) - idx = f.templateLayout.indexOf(w) - r = f.templateLayout.getItemPosition(idx) - f.templateLayout.removeWidget(w) - w.hide() - w.deleteLater() - w = ResizingTextEdit(self) - setattr(f, e, w) - f.templateLayout.addWidget(w, r[0], r[1]) - c = self.connect - c(f.cardList, SIGNAL("activated(int)"), self.cardChanged) - c(f.editTemplates, SIGNAL("clicked()"), self.onEdit) - c(f.cardQuestion, SIGNAL("textChanged()"), self.formatChanged) - c(f.cardAnswer, SIGNAL("textChanged()"), self.formatChanged) - c(f.alignment, SIGNAL("activated(int)"), self.saveCard) - c(f.background, SIGNAL("clicked()"), - lambda w=f.background:\ - self.chooseColour(w, "card")) - c(f.questionInAnswer, SIGNAL("clicked()"), self.saveCard) - c(f.allowEmptyAnswer, SIGNAL("clicked()"), self.saveCard) - c(f.typeAnswer, SIGNAL("activated(int)"), self.saveCard) - c(f.flipButton, SIGNAL("clicked()"), self.onFlip) - c(f.clozectx, SIGNAL("clicked()"), self.saveCard) - def linkClicked(url): - QDesktopServices.openUrl(QUrl(url)) - f.preview.page().setLinkDelegationPolicy( - QWebPage.DelegateExternalLinks) - self.connect(f.preview, - SIGNAL("linkClicked(QUrl)"), - linkClicked) - f.alignment.addItems(alignmentLabels().values()) - self.typeFieldNames = self.mm.fieldMap(self.model) - s = [_("Don't ask me to type in the answer")] - s += [_("Compare with field '%s'") % fi - for fi in self.typeFieldNames.keys()] - f.typeAnswer.insertItems(0, s) - - def formatToScreen(self, fmt): - fmt = fmt.replace("}}
", "}}\n") - return fmt - - def screenToFormat(self, fmt): - fmt = fmt.replace("}}\n", "}}
") - return fmt - - def onEdit(self): - aqt.templates.Templates(self.mw, self.model, self) - self.reload() - - def formatChanged(self): - if self.updatingCards: + def saveField(self): + # not initialized yet? + if self.currentIdx is None: return - text = unicode(self.form.cardQuestion.toPlainText()) - self.card.template()['qfmt'] = self.screenToFormat(text) - text = unicode(self.form.cardAnswer.toPlainText()) - self.card.template()['afmt'] = self.screenToFormat(text) - self.renderPreview() - - def onFlip(self): - q = unicode(self.form.cardQuestion.toPlainText()) - a = unicode(self.form.cardAnswer.toPlainText()) - self.form.cardAnswer.setPlainText(q) - self.form.cardQuestion.setPlainText(a) - - def readCard(self): - self.updatingCards = True - t = self.card.template() + idx = self.currentIdx + fld = self.model['flds'][idx] f = self.form - f.background.setPalette(QPalette(QColor(t['bg']))) - f.cardQuestion.setPlainText(self.formatToScreen(t['qfmt'])) - f.cardAnswer.setPlainText(self.formatToScreen(t['afmt'])) - f.questionInAnswer.setChecked(t['hideQ']) - f.allowEmptyAnswer.setChecked(t['emptyAns']) - f.alignment.setCurrentIndex(t['align']) - if t['typeAns'] is None: - f.typeAnswer.setCurrentIndex(0) - else: - f.typeAnswer.setCurrentIndex(t['typeAns'] + 1) - # model-level, but there's nowhere else to put this - f.clozectx.setChecked(self.model['clozectx']) - self.updatingCards = False + fld['font'] = f.fontFamily.currentFont().family() + fld['size'] = f.fontSize.value() + fld['sticky'] = f.sticky.isChecked() + fld['rtl'] = f.rtl.isChecked() - def fillCardList(self): - self.form.cardList.clear() - cards = [] - idx = 0 - for n, c in enumerate(self.cards): - if c.ord == self.ord: - cards.append(_("%s (current)") % c.template()['name']) - idx = n - else: - cards.append(c.template()['name']) - self.form.cardList.addItems(cards) - self.form.cardList.setCurrentIndex(idx) - self.cardChanged(idx) - self.form.cardList.setFocus() - - def cardChanged(self, idx): - self.card = self.cards[idx] - self.readCard() - self.renderPreview() - - def saveCard(self): - if self.updatingCards: - return - t = self.card.template() - t['align'] = self.form.alignment.currentIndex() - t['bg'] = unicode( - self.form.background.palette().window().color().name()) - t['hideQ'] = self.form.questionInAnswer.isChecked() - t['emptyAns'] = self.form.allowEmptyAnswer.isChecked() - idx = self.form.typeAnswer.currentIndex() - if not idx: - t['typeAns'] = None - else: - t['typeAns'] = idx-1 - self.model['clozectx'] = self.form.clozectx.isChecked() - self.renderPreview() - - def chooseColour(self, button, type="field"): - new = QColorDialog.getColor(button.palette().window().color(), self, - _("Choose Color"), - QColorDialog.DontUseNativeDialog) - if new.isValid(): - button.setPalette(QPalette(new)) - if type == "field": - self.saveField() - else: - self.saveCard() - - def renderPreview(self): - c = self.card - styles = self.model['css'] - styles += "\n.cloze { font-weight: bold; color: blue; }" - self.form.preview.setHtml( - ('%s' % - (getBase(self.col), c.cssClass())) + - "" + - mungeQA(c.q(reload=True)) + - self.maybeTextInput() + - "
" + - mungeQA(c.a()) - + "") - clearAudioQueue() - if c.id not in self.playedAudio: - playFromText(c.q()) - playFromText(c.a()) - self.playedAudio[c.id] = True - - def maybeTextInput(self): - if self.card.template()['typeAns'] is not None: - return "
" - return "" + def reject(self): + self.saveField() + self.mm.save(self.model) + self.mw.reset() + QDialog.reject(self) def accept(self): self.reject() - def reject(self): - return QDialog.reject(self) - self.mm.save(self.model) - saveGeom(self, "CardLayout") - saveSplitter(self.form.splitter, "clayout") - self.mw.reset() - return QDialog.reject(self) - - - modified = False - self.mw.startProgress() - self.col.updateProgress(_("Applying changes...")) - reset=True - if len(self.fieldOrdinalUpdatedIds) > 0: - self.col.rebuildFieldOrdinals(self.model.id, self.fieldOrdinalUpdatedIds) - modified = True - if self.needFieldRebuild: - modified = True - if modified: - self.note.model.setModified() - self.col.flushMod() - if self.noteedit and self.noteedit.onChange: - self.noteedit.onChange("all") - reset=False - if reset: - self.mw.reset() - self.col.finishProgress() - QDialog.reject(self) - def onHelp(self): - openHelp("CardLayout") - - # Fields - ########################################################################## - - def setupFields(self): - self.fieldOrdinalUpdatedIds = [] - self.updatingFields = False - self.needFieldRebuild = False - c = self.connect; f = self.form - sc = SIGNAL("stateChanged(int)") - cl = SIGNAL("clicked()") - c(f.fieldAdd, cl, self.addField) - c(f.fieldDelete, cl, self.deleteField) - c(f.fieldUp, cl, self.moveFieldUp) - c(f.fieldDown, cl, self.moveFieldDown) - c(f.preserveWhitespace, sc, self.saveField) - c(f.fieldUnique, sc, self.saveField) - c(f.fieldRequired, sc, self.saveField) - c(f.sticky, sc, self.saveField) - c(f.fieldList, SIGNAL("currentRowChanged(int)"), - self.fieldChanged) - c(f.fieldName, SIGNAL("lostFocus()"), - self.saveField) - c(f.fontFamily, SIGNAL("currentFontChanged(QFont)"), - self.saveField) - c(f.fontSize, SIGNAL("valueChanged(int)"), - self.saveField) - c(f.fontSizeEdit, SIGNAL("valueChanged(int)"), - self.saveField) - w = self.form.fontColour - c(w, SIGNAL("clicked()"), - lambda w=w: self.chooseColour(w)) - c(self.form.rtl, - SIGNAL("stateChanged(int)"), - self.saveField) - - def fieldChanged(self): - row = self.form.fieldList.currentRow() - if row == -1: - row = 0 - self.field = self.model['flds'][row] - self.readField() - self.enableFieldMoveButtons() - - def readField(self): - fld = self.field - f = self.form - self.updatingFields = True - f.fieldName.setText(fld['name']) - f.fieldUnique.setChecked(fld['uniq']) - f.fieldRequired.setChecked(fld['req']) - f.fontFamily.setCurrentFont(QFont(fld['font'])) - f.fontSize.setValue(fld['qsize']) - f.fontSizeEdit.setValue(fld['esize']) - f.fontColour.setPalette(QPalette(QColor(fld['qcol']))) - f.rtl.setChecked(fld['rtl']) - f.preserveWhitespace.setChecked(fld['pre']) - f.sticky.setChecked(fld['sticky']) - self.updatingFields = False - - def saveField(self, *args): - self.needFieldRebuild = True - if self.updatingFields: - return - self.updatingFields = True - fld = self.field - # get name; we'll handle it last - name = unicode(self.form.fieldName.text()) - if not name: - return - fld['uniq'] = self.form.fieldUnique.isChecked() - fld['req'] = self.form.fieldRequired.isChecked() - fld['font'] = unicode( - self.form.fontFamily.currentFont().family()) - fld['qsize'] = self.form.fontSize.value() - fld['esize'] = self.form.fontSizeEdit.value() - fld['qcol'] = str( - self.form.fontColour.palette().window().color().name()) - fld['rtl'] = self.form.rtl.isChecked() - fld['pre'] = self.form.preserveWhitespace.isChecked() - fld['sticky'] = self.form.sticky.isChecked() - self.updatingFields = False - if fld['name'] != name: - self.mm.renameField(self.model, fld, name) - # as the field name has changed, we have to regenerate cards - self.cards = self.col.previewCards(self.note, self.type) - self.cardChanged(0) - self.renderPreview() - self.fillFieldList() - - def fillFieldList(self, row = None): - oldRow = self.form.fieldList.currentRow() - if oldRow == -1: - oldRow = 0 - self.form.fieldList.clear() - n = 1 - for field in self.model['flds']: - label = field['name'] - item = QListWidgetItem(label) - self.form.fieldList.addItem(item) - n += 1 - count = self.form.fieldList.count() - if row != None: - self.form.fieldList.setCurrentRow(row) - else: - while (count > 0 and oldRow > (count - 1)): - oldRow -= 1 - self.form.fieldList.setCurrentRow(oldRow) - self.enableFieldMoveButtons() - - def enableFieldMoveButtons(self): - row = self.form.fieldList.currentRow() - if row < 1: - self.form.fieldUp.setEnabled(False) - else: - self.form.fieldUp.setEnabled(True) - if row == -1 or row >= (self.form.fieldList.count() - 1): - self.form.fieldDown.setEnabled(False) - else: - self.form.fieldDown.setEnabled(True) - - def addField(self): - f = self.mm.newField(self.model) - l = len(self.model['flds']) - f['name'] = _("Field %d") % l - self.mw.progress.start() - self.mm.addField(self.model, f) - self.mw.progress.finish() - self.reload() - self.form.fieldList.setCurrentRow(l) - self.form.fieldName.setFocus() - self.form.fieldName.selectAll() - - def deleteField(self): - row = self.form.fieldList.currentRow() - if row == -1: - return - if len(self.model.fields) < 2: - showInfo(_("Please add a new field first.")) - return - if askUser(_("Delete this field and its data from all notes?")): - self.mw.progress.start() - self.model.delField(self.field) - self.mw.progress.finish() - # need to update q/a format - self.reload() - - def moveFieldUp(self): - row = self.form.fieldList.currentRow() - if row == -1: - return - if row == 0: - return - self.mw.progress.start() - self.model.moveField(self.field, row-1) - self.mw.progress.finish() - self.form.fieldList.setCurrentRow(row-1) - self.reload() - - def moveFieldDown(self): - row = self.form.fieldList.currentRow() - if row == -1: - return - if row == len(self.model.fields) - 1: - return - self.mw.progress.start() - self.model.moveField(self.field, row+1) - self.mw.progress.finish() - self.form.fieldList.setCurrentRow(row+1) - self.reload() + openHelp("Fields") diff --git a/aqt/main.py b/aqt/main.py index b922378e4..d692ce029 100755 --- a/aqt/main.py +++ b/aqt/main.py @@ -193,6 +193,7 @@ Are you sure?"""): # then load collection and launch into the deck browser print "fixme: safeguard against multiple instances" self.col = Collection(self.pm.collectionPath()) + self.progress.setupDB(self.col.db) # skip the reset step; open overview directly self.moveToState("review") @@ -212,8 +213,6 @@ Are you sure?"""): getattr(self, "_"+state+"State")(oldState, *args) def _deckBrowserState(self, oldState): - self.disableDeckMenuItems() - self.closeAllWindows() self.deckBrowser.show() def _colLoadingState(self, oldState): @@ -429,27 +428,33 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors") else: aw.close() - def close(self, showBrowser=True): - "Close current deck." + def close(self): + "Close and backup collection." if not self.col: return - # if we were cramming, restore the standard scheduler - if self.col.stdSched(): - self.col.reset() runHook("deckClosing") - print "focusOut() should be handled with deckClosing now" + #self.col.close() + self.backup() self.closeAllWindows() self.col.close() self.col = None - if showBrowser: - self.moveToState("deckBrowser") + + # Syncing + ########################################################################## + + def backup(self): + print "backup" # Syncing ########################################################################## def onSync(self): - return - return showInfo("sync not yet implemented") + from aqt.sync import Syncer + # close collection if loaded + if self.col: + self.col.close() + # + Syncer() # Tools ########################################################################## @@ -484,11 +489,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors") def closeEvent(self, event): "User hit the X button, etc." - print "fixme: exit from edit current, review, etc" - if self.state == "editCurrentNote": - event.ignore() - return self.moveToState("saveEdit") - self.close(showBrowser=False) + self.close() # if self.pm.profile['syncOnProgramOpen']: # self.showBrowser = False # self.syncDeck(interactive=False) @@ -857,118 +858,9 @@ Please choose a new deck name:""")) def onSchemaMod(self, arg): return askUser(_("""\ -This operation can't be merged when syncing, so the next \ -sync will overwrite any changes made on other devices that \ -haven't been synced here yet. Continue?""")) - - # Media locations - ########################################################################## - -# def setupMedia(self, deck): -# print "setup media" -# return -# prefix = self.pm.profile['mediaLocation'] -# prev = deck.getVar("mediaLocation") or "" -# # set the media prefix -# if not prefix: -# next = "" -# elif prefix == "dropbox": -# p = self.dropboxFolder() -# next = os.path.join(p, "Public", "Anki") -# else: -# next = prefix -# # check if the media has moved -# migrateFrom = None -# if prev != next: -# # check if they were using plugin -# if not prev: -# p = self.dropboxFolder() -# p = os.path.join(p, "Public") -# deck.mediaPrefix = p -# migrateFrom = deck.mediaDir() -# if not migrateFrom: -# # find the old location -# deck.mediaPrefix = prev -# dir = deck.mediaDir() -# if dir and os.listdir(dir): -# # it contains files; we'll need to migrate -# migrateFrom = dir -# # setup new folder -# deck.mediaPrefix = next -# if migrateFrom: -# # force creation of new folder -# dir = deck.mediaDir(create=True) -# # migrate old files -# self.migrateMedia(migrateFrom, dir) -# else: -# # chdir if dir exists -# dir = deck.mediaDir() -# # update location -# deck.setVar("mediaLocation", next, mod=False) -# if dir and prefix == "dropbox": -# self.setupDropbox(deck) - -# def migrateMedia(self, from_, to): -# if from_ == to: -# return -# files = os.listdir(from_) -# skipped = False -# for f in files: -# src = os.path.join(from_, f) -# dst = os.path.join(to, f) -# if not os.path.isfile(src): -# skipped = True -# continue -# if not os.path.exists(dst): -# shutil.copy2(src, dst) -# if not skipped: -# # everything copied, we can remove old folder -# shutil.rmtree(from_, ignore_errors=True) - -# def dropboxFolder(self): -# try: -# import aqt.dropbox as db -# p = db.getPath() -# except: -# if isWin: -# s = QSettings(QSettings.UserScope, "Microsoft", "Windows") -# s.beginGroup("CurrentVersion/Explorer/Shell Folders") -# p = os.path.join(s.value("Personal"), "My Dropbox") -# else: -# p = os.path.expanduser("~/Dropbox") -# return p - -# def setupDropbox(self, deck): -# if not self.pm.profile['dropboxPublicFolder']: -# # put a file in the folder -# open(os.path.join( -# deck.mediaPrefix, "right-click-me.txt"), "w").write("") -# # tell user what to do -# showInfo(_("""\ -# A file called right-click-me.txt has been placed in DropBox's public folder. \ -# After clicking OK, this folder will appear. Please right click on the file (\ -# command+click on a Mac), choose DropBox>Copy Public Link, and paste the \ -# link into Anki.""")) -# # open folder and text prompt -# self.onOpenPluginFolder(deck.mediaPrefix) -# txt = getText(_("Paste path here:"), parent=self) -# if txt[0]: -# fail = False -# if not txt[0].lower().startswith("http"): -# fail = True -# if not txt[0].lower().endswith("right-click-me.txt"): -# fail = True -# if fail: -# showInfo(_("""\ -# That doesn't appear to be a public link. You'll be asked again when the deck \ -# is next loaded.""")) -# else: -# self.pm.profile['dropboxPublicFolder'] = os.path.dirname(txt[0]) -# if self.pm.profile['dropboxPublicFolder']: -# # update media url -# deck.setVar( -# "mediaURL", self.pm.profile['dropboxPublicFolder'] + "/" + -# os.path.basename(deck.mediaDir()) + "/") +This operation can't be merged when syncing, so if you have made \ +changes on other devices that haven't been synced to this device yet, \ +they will be lost. Are you sure you want to continue?""")) # Advanced features ########################################################################## diff --git a/aqt/progress.py b/aqt/progress.py index 6c641675a..69ff92f94 100644 --- a/aqt/progress.py +++ b/aqt/progress.py @@ -25,10 +25,10 @@ class ProgressManager(object): ########################################################################## def setupDB(self, db): - "Install a handler in the current deck." + "Install a handler in the current DB." self.lastDbProgress = 0 self.inDB = False - db.set_progress_handler(self._dbProgress, 100000) + db.set_progress_handler(self._dbProgress, 10000) def _dbProgress(self): "Called from SQLite." diff --git a/aqt/sync.py b/aqt/sync.py index 46bfe2400..b6af7f07f 100755 --- a/aqt/sync.py +++ b/aqt/sync.py @@ -5,15 +5,14 @@ from aqt.qt import * import os, types, socket, time, traceback import aqt import anki -from anki.sync import SyncClient, HttpSyncServerProxy, copyLocalMedia -from anki.sync import SYNC_HOST, SYNC_PORT +#from anki.sync import SyncClient, HttpSyncServerProxy, copyLocalMedia from +#anki.sync import SYNC_HOST, SYNC_PORT from anki.errors import * -from anki import Deck from anki.db import sqlite import aqt.forms from anki.hooks import addHook, removeHook -class SyncManager(object): +class Syncer(object): # Syncing ########################################################################## diff --git a/designer/fields.ui b/designer/fields.ui index 695f33b9b..6ba5507de 100644 --- a/designer/fields.ui +++ b/designer/fields.ui @@ -6,13 +6,16 @@ 0 0 - 403 + 412 352 Fields + + true + @@ -37,62 +40,28 @@ - - - - - :/icons/list-add.png:/icons/list-add.png - - - false + Add - - - - - :/icons/editdelete.png:/icons/editdelete.png - - - false + Delete - - - Move selected field up - + - - - - - :/icons/arrow-up.png:/icons/arrow-up.png - - - false + Rename - - - Move selected field down - + - - - - - :/icons/arrow-down.png:/icons/arrow-down.png - - - false + Reposition @@ -115,27 +84,14 @@ - - - - - - Name - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - Editing Font - + @@ -145,14 +101,14 @@ - + Reverse text direction (RTL) - + 5 @@ -162,21 +118,21 @@ - + - Remember last input + Remember last input when adding - + Options - + Sort by this field in the browser @@ -201,11 +157,11 @@ fieldList fieldAdd fieldDelete - fieldUp - fieldDown - fieldName + fieldRename + fieldPosition fontFamily fontSize + sortField sticky rtl buttonBox