From 73221680c87d8bfe2ca220411d05055e49214fd0 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Fri, 6 Feb 2009 23:27:30 +0900 Subject: [PATCH] index sort, remove select facts, more - fetch id in advance, everything else dynamically - build index for selected column - remove 'select facts', it's no longer required - remove 'priority', it's not used - update icons --- ankiqt/config.py | 1 - ankiqt/ui/cardlist.py | 71 +++++++++++++++++++------------ designer/cardlist.ui | 9 +++- designer/main.ui | 28 ++++++------ icons.qrc | 3 ++ icons/download.png | Bin 0 -> 1536 bytes icons/preferences-plugin.png | Bin 0 -> 1763 bytes icons/system-software-update.png | Bin 0 -> 2588 bytes 8 files changed, 71 insertions(+), 41 deletions(-) create mode 100644 icons/download.png create mode 100644 icons/preferences-plugin.png create mode 100644 icons/system-software-update.png diff --git a/ankiqt/config.py b/ankiqt/config.py index 8466ad459..b043d341f 100644 --- a/ankiqt/config.py +++ b/ankiqt/config.py @@ -63,7 +63,6 @@ class Config(dict): 'showLastCardContent': False, 'showTrayIcon': False, 'showTimer': True, - 'showSuspendedCards': True, 'simpleToolbar': True, 'scrollToAnswer': True, 'qaDivider': True, diff --git a/ankiqt/ui/cardlist.py b/ankiqt/ui/cardlist.py index c295b5152..4a8543d10 100644 --- a/ankiqt/ui/cardlist.py +++ b/ankiqt/ui/cardlist.py @@ -18,6 +18,13 @@ from anki.db import * from anki.stats import CardStats from anki.hooks import runHook, addHook +CARD_ID = 0 +CARD_QUESTION = 1 +CARD_ANSWER = 2 +CARD_DUE = 3 +CARD_REPS = 4 +CARD_FACTID = 5 + # Deck editor ########################################################################## @@ -48,7 +55,7 @@ class DeckModel(QAbstractTableModel): return len(self.cards) def columnCount(self, index): - return len(self.columns) + return 3 def data(self, index, role): if not index.isValid(): @@ -58,6 +65,9 @@ class DeckModel(QAbstractTableModel): f.setPixelSize(12) return QVariant(f) elif role == Qt.DisplayRole or role == Qt.EditRole: + if len(self.cards[index.row()]) == 1: + # not cached yet + self.updateCard(index) s = self.columns[index.column()][1](index) s = s.replace("
", u" ") s = s.replace("\n", u" ") @@ -111,16 +121,13 @@ class DeckModel(QAbstractTableModel): ads = [] if searchLimit: ads.append(searchLimit) if tagLimit: ads.append(tagLimit) - if not self.parent.config['showSuspendedCards']: - ads.append("cards.priority != 0") ads = " and ".join(ads) if isinstance(self.sortKey, types.StringType): # card property sort = "order by cards." + self.sortKey if self.sortKey in ("question", "answer"): sort += " collate nocase" - query = ("select id, priority, question, answer, due, " - "reps, factId from cards ") + query = ("select id from cards ") if ads: query += "where %s " % ads query += sort @@ -138,8 +145,7 @@ class DeckModel(QAbstractTableModel): order = "fields.value collate nocase" if ads: ads = " and " + ads - query = ("select cards.id, cards.priority, cards.question, " - "cards.answer, cards.due, cards.reps, cards.factId " + query = ("select cards.id " "from fields, cards where fields.fieldModelId in (%s) " "and fields.factId = cards.factId" + ads + " order by cards.ordinal, %s") % (fields, order) @@ -152,7 +158,7 @@ class DeckModel(QAbstractTableModel): def updateCard(self, index): try: self.cards[index.row()] = self.deck.s.first(""" - select id, priority, question, answer, due, reps, factId + select id, question, answer, due, reps, factId from cards where id = :id""", id=self.cards[index.row()][0]) self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, self.index(index.row(), 1)) @@ -172,22 +178,19 @@ class DeckModel(QAbstractTableModel): except IndexError: return None - def isDeleted(self, id): - return id in self.deleted - def cardIndex(self, card): "Return the index of CARD, if currently displayed." return self.cards.index(card) def currentQuestion(self, index): - return self.cards[index.row()][2] + return self.cards[index.row()][CARD_QUESTION] def currentAnswer(self, index): - return self.cards[index.row()][3] + return self.cards[index.row()][CARD_ANSWER] def nextDue(self, index): - d = self.cards[index.row()][4] - reps = self.cards[index.row()][5] + d = self.cards[index.row()][CARD_DUE] + reps = self.cards[index.row()][CARD_REPS] secs = d - time.time() if secs <= 0: if not reps: @@ -208,6 +211,8 @@ class EditDeck(QMainWindow): self.currentRow = None self.dialog = ankiqt.forms.cardlist.Ui_MainWindow() self.dialog.setupUi(self) + restoreGeom(self, "editor") + restoreSplitter(self.dialog.splitter, "editor") # flush all changes before we load self.deck.s.flush() self.model = DeckModel(self.parent, self.parent.deck) @@ -233,8 +238,6 @@ class EditDeck(QMainWindow): ui.dialogs.open("CardList", self) self.drawTags() self.updateFilterLabel() - restoreGeom(self, "editor") - restoreSplitter(self.dialog.splitter, "editor") self.show() self.updateSearch() if self.parent.currentCard: @@ -321,6 +324,7 @@ class EditDeck(QMainWindow): self.sortKey = "factor" else: self.sortKey = ("field", self.sortFields[idx-8]) + self.rebuildSortIndex(self.sortKey) self.sortIndex = idx if idx <= 7: self.config['sortIndex'] = idx @@ -331,6 +335,28 @@ class EditDeck(QMainWindow): self.onEvent() self.focusCurrentCard() + def rebuildSortIndex(self, key): + if key not in ( + "question", "answer", "created", "modified", "due", "interval", + "reps", "factor"): + return + old = self.deck.s.scalar("select sql from sqlite_master where name = :k", + k="ix_cards_sort") + if old and key in old: + return + self.parent.setProgressParent(self) + self.deck.startProgress(2) + self.deck.updateProgress(_("Building Index...")) + self.deck.s.statement("drop index if exists ix_cards_sort") + self.deck.updateProgress() + if key in ("question", "answer"): + key = key + " collate nocase" + self.deck.s.statement( + "create index ix_cards_sort on cards (%s)" % key) + self.deck.s.statement("analyze") + self.deck.finishProgress() + self.parent.setProgressParent(None) + def tagChanged(self, idx): if idx == 0: self.currentTag = None @@ -367,7 +393,7 @@ class EditDeck(QMainWindow): self.model.updateCard(self.currentRow) def filterTextChanged(self): - interval = 500 + interval = 300 if self.filterTimer: self.filterTimer.setInterval(interval) else: @@ -432,7 +458,6 @@ class EditDeck(QMainWindow): # edit self.connect(self.dialog.actionUndo, SIGNAL("triggered()"), self.onUndo) self.connect(self.dialog.actionRedo, SIGNAL("triggered()"), self.onRedo) - self.connect(self.dialog.actionSelectFacts, SIGNAL("triggered()"), self.selectFacts) self.connect(self.dialog.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection) self.connect(self.dialog.actionReverseOrder, SIGNAL("triggered()"), self.reverseOrder) # jumps @@ -657,14 +682,6 @@ where id in %s""" % ids2str(sf)) # Edit: selection ###################################################################### - def selectFacts(self): - sm = self.dialog.tableView.selectionModel() - cardIds = dict([(x, 1) for x in self.selectedFactsAsCards()]) - for i, card in enumerate(self.model.cards): - if card.id in cardIds: - sm.select(self.model.index(i, 0), - QItemSelectionModel.Select | QItemSelectionModel.Rows) - def invertSelection(self): sm = self.dialog.tableView.selectionModel() items = sm.selection() diff --git a/designer/cardlist.ui b/designer/cardlist.ui index 818dfd766..dda0ab189 100644 --- a/designer/cardlist.ui +++ b/designer/cardlist.ui @@ -181,7 +181,6 @@ - @@ -385,11 +384,19 @@ + + + :/icons/help.png:/icons/help.png + &Guide... + + + :/icons/system-software-update.png:/icons/system-software-update.png + Change &Model... diff --git a/designer/main.ui b/designer/main.ui index d6a8a51c5..8b211797a 100644 --- a/designer/main.ui +++ b/designer/main.ui @@ -26,9 +26,9 @@ 0 - 63 + 69 751 - 418 + 413 @@ -382,7 +382,7 @@ 0 0 474 - 60 + 57 @@ -405,7 +405,7 @@ 0 0 474 - 358 + 356 @@ -1192,7 +1192,7 @@ 0 0 751 - 21 + 23 @@ -1305,6 +1305,10 @@ P&lugins + + + :/icons/preferences-plugin.png:/icons/preferences-plugin.png + Startup @@ -1337,9 +1341,9 @@ 0 - 481 + 482 751 - 21 + 20 @@ -1353,9 +1357,9 @@ 0 - 21 + 23 751 - 42 + 46 @@ -1567,10 +1571,10 @@ - :/icons/go-home.png:/icons/go-home.png + :/icons/help.png:/icons/help.png - &Start Here... + Documentation @@ -1850,7 +1854,7 @@ - :/icons/khtml_kget.png:/icons/khtml_kget.png + :/icons/download.png:/icons/download.png &Get More Decks... diff --git a/icons.qrc b/icons.qrc index 7a7b53f30..47040d4ee 100644 --- a/icons.qrc +++ b/icons.qrc @@ -1,5 +1,8 @@ + icons/download.png + icons/preferences-plugin.png + icons/system-software-update.png icons/media-playback-stop.png icons/media-record.png icons/view-calendar-tasks.png diff --git a/icons/download.png b/icons/download.png new file mode 100644 index 0000000000000000000000000000000000000000..3f2169268bdeb51aec550f16c23fbde322d6f263 GIT binary patch literal 1536 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 FV1f>+LjC{% literal 0 HcmV?d00001 diff --git a/icons/system-software-update.png b/icons/system-software-update.png new file mode 100644 index 0000000000000000000000000000000000000000..00bb4480c66cc2dc47760ce852f5e299efcb6876 GIT binary patch literal 2588 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