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
This commit is contained in:
Damien Elmes 2009-02-06 23:27:30 +09:00
parent 91ffc61752
commit 73221680c8
8 changed files with 71 additions and 41 deletions

View file

@ -63,7 +63,6 @@ class Config(dict):
'showLastCardContent': False, 'showLastCardContent': False,
'showTrayIcon': False, 'showTrayIcon': False,
'showTimer': True, 'showTimer': True,
'showSuspendedCards': True,
'simpleToolbar': True, 'simpleToolbar': True,
'scrollToAnswer': True, 'scrollToAnswer': True,
'qaDivider': True, 'qaDivider': True,

View file

@ -18,6 +18,13 @@ from anki.db import *
from anki.stats import CardStats from anki.stats import CardStats
from anki.hooks import runHook, addHook 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 # Deck editor
########################################################################## ##########################################################################
@ -48,7 +55,7 @@ class DeckModel(QAbstractTableModel):
return len(self.cards) return len(self.cards)
def columnCount(self, index): def columnCount(self, index):
return len(self.columns) return 3
def data(self, index, role): def data(self, index, role):
if not index.isValid(): if not index.isValid():
@ -58,6 +65,9 @@ class DeckModel(QAbstractTableModel):
f.setPixelSize(12) f.setPixelSize(12)
return QVariant(f) return QVariant(f)
elif role == Qt.DisplayRole or role == Qt.EditRole: 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 = self.columns[index.column()][1](index)
s = s.replace("<br>", u" ") s = s.replace("<br>", u" ")
s = s.replace("\n", u" ") s = s.replace("\n", u" ")
@ -111,16 +121,13 @@ class DeckModel(QAbstractTableModel):
ads = [] ads = []
if searchLimit: ads.append(searchLimit) if searchLimit: ads.append(searchLimit)
if tagLimit: ads.append(tagLimit) if tagLimit: ads.append(tagLimit)
if not self.parent.config['showSuspendedCards']:
ads.append("cards.priority != 0")
ads = " and ".join(ads) ads = " and ".join(ads)
if isinstance(self.sortKey, types.StringType): if isinstance(self.sortKey, types.StringType):
# card property # card property
sort = "order by cards." + self.sortKey sort = "order by cards." + self.sortKey
if self.sortKey in ("question", "answer"): if self.sortKey in ("question", "answer"):
sort += " collate nocase" sort += " collate nocase"
query = ("select id, priority, question, answer, due, " query = ("select id from cards ")
"reps, factId from cards ")
if ads: if ads:
query += "where %s " % ads query += "where %s " % ads
query += sort query += sort
@ -138,8 +145,7 @@ class DeckModel(QAbstractTableModel):
order = "fields.value collate nocase" order = "fields.value collate nocase"
if ads: if ads:
ads = " and " + ads ads = " and " + ads
query = ("select cards.id, cards.priority, cards.question, " query = ("select cards.id "
"cards.answer, cards.due, cards.reps, cards.factId "
"from fields, cards where fields.fieldModelId in (%s) " "from fields, cards where fields.fieldModelId in (%s) "
"and fields.factId = cards.factId" + ads + "and fields.factId = cards.factId" + ads +
" order by cards.ordinal, %s") % (fields, order) " order by cards.ordinal, %s") % (fields, order)
@ -152,7 +158,7 @@ class DeckModel(QAbstractTableModel):
def updateCard(self, index): def updateCard(self, index):
try: try:
self.cards[index.row()] = self.deck.s.first(""" 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]) from cards where id = :id""", id=self.cards[index.row()][0])
self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
index, self.index(index.row(), 1)) index, self.index(index.row(), 1))
@ -172,22 +178,19 @@ class DeckModel(QAbstractTableModel):
except IndexError: except IndexError:
return None return None
def isDeleted(self, id):
return id in self.deleted
def cardIndex(self, card): def cardIndex(self, card):
"Return the index of CARD, if currently displayed." "Return the index of CARD, if currently displayed."
return self.cards.index(card) return self.cards.index(card)
def currentQuestion(self, index): def currentQuestion(self, index):
return self.cards[index.row()][2] return self.cards[index.row()][CARD_QUESTION]
def currentAnswer(self, index): def currentAnswer(self, index):
return self.cards[index.row()][3] return self.cards[index.row()][CARD_ANSWER]
def nextDue(self, index): def nextDue(self, index):
d = self.cards[index.row()][4] d = self.cards[index.row()][CARD_DUE]
reps = self.cards[index.row()][5] reps = self.cards[index.row()][CARD_REPS]
secs = d - time.time() secs = d - time.time()
if secs <= 0: if secs <= 0:
if not reps: if not reps:
@ -208,6 +211,8 @@ class EditDeck(QMainWindow):
self.currentRow = None self.currentRow = None
self.dialog = ankiqt.forms.cardlist.Ui_MainWindow() self.dialog = ankiqt.forms.cardlist.Ui_MainWindow()
self.dialog.setupUi(self) self.dialog.setupUi(self)
restoreGeom(self, "editor")
restoreSplitter(self.dialog.splitter, "editor")
# flush all changes before we load # flush all changes before we load
self.deck.s.flush() self.deck.s.flush()
self.model = DeckModel(self.parent, self.parent.deck) self.model = DeckModel(self.parent, self.parent.deck)
@ -233,8 +238,6 @@ class EditDeck(QMainWindow):
ui.dialogs.open("CardList", self) ui.dialogs.open("CardList", self)
self.drawTags() self.drawTags()
self.updateFilterLabel() self.updateFilterLabel()
restoreGeom(self, "editor")
restoreSplitter(self.dialog.splitter, "editor")
self.show() self.show()
self.updateSearch() self.updateSearch()
if self.parent.currentCard: if self.parent.currentCard:
@ -321,6 +324,7 @@ class EditDeck(QMainWindow):
self.sortKey = "factor" self.sortKey = "factor"
else: else:
self.sortKey = ("field", self.sortFields[idx-8]) self.sortKey = ("field", self.sortFields[idx-8])
self.rebuildSortIndex(self.sortKey)
self.sortIndex = idx self.sortIndex = idx
if idx <= 7: if idx <= 7:
self.config['sortIndex'] = idx self.config['sortIndex'] = idx
@ -331,6 +335,28 @@ class EditDeck(QMainWindow):
self.onEvent() self.onEvent()
self.focusCurrentCard() 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): def tagChanged(self, idx):
if idx == 0: if idx == 0:
self.currentTag = None self.currentTag = None
@ -367,7 +393,7 @@ class EditDeck(QMainWindow):
self.model.updateCard(self.currentRow) self.model.updateCard(self.currentRow)
def filterTextChanged(self): def filterTextChanged(self):
interval = 500 interval = 300
if self.filterTimer: if self.filterTimer:
self.filterTimer.setInterval(interval) self.filterTimer.setInterval(interval)
else: else:
@ -432,7 +458,6 @@ class EditDeck(QMainWindow):
# edit # edit
self.connect(self.dialog.actionUndo, SIGNAL("triggered()"), self.onUndo) self.connect(self.dialog.actionUndo, SIGNAL("triggered()"), self.onUndo)
self.connect(self.dialog.actionRedo, SIGNAL("triggered()"), self.onRedo) 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.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection)
self.connect(self.dialog.actionReverseOrder, SIGNAL("triggered()"), self.reverseOrder) self.connect(self.dialog.actionReverseOrder, SIGNAL("triggered()"), self.reverseOrder)
# jumps # jumps
@ -657,14 +682,6 @@ where id in %s""" % ids2str(sf))
# Edit: selection # 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): def invertSelection(self):
sm = self.dialog.tableView.selectionModel() sm = self.dialog.tableView.selectionModel()
items = sm.selection() items = sm.selection()

View file

@ -181,7 +181,6 @@
<addaction name="actionRedo" /> <addaction name="actionRedo" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionSelectAll" /> <addaction name="actionSelectAll" />
<addaction name="actionSelectFacts" />
<addaction name="actionInvertSelection" /> <addaction name="actionInvertSelection" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionReverseOrder" /> <addaction name="actionReverseOrder" />
@ -385,11 +384,19 @@
</property> </property>
</action> </action>
<action name="actionGuide" > <action name="actionGuide" >
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/help.png</normaloff>:/icons/help.png</iconset>
</property>
<property name="text" > <property name="text" >
<string>&amp;Guide...</string> <string>&amp;Guide...</string>
</property> </property>
</action> </action>
<action name="actionChangeModel" > <action name="actionChangeModel" >
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/system-software-update.png</normaloff>:/icons/system-software-update.png</iconset>
</property>
<property name="text" > <property name="text" >
<string>Change &amp;Model...</string> <string>Change &amp;Model...</string>
</property> </property>

View file

@ -26,9 +26,9 @@
<property name="geometry" > <property name="geometry" >
<rect> <rect>
<x>0</x> <x>0</x>
<y>63</y> <y>69</y>
<width>751</width> <width>751</width>
<height>418</height> <height>413</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy" > <property name="sizePolicy" >
@ -382,7 +382,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>474</width> <width>474</width>
<height>60</height> <height>57</height>
</rect> </rect>
</property> </property>
</widget> </widget>
@ -405,7 +405,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>474</width> <width>474</width>
<height>358</height> <height>356</height>
</rect> </rect>
</property> </property>
</widget> </widget>
@ -1192,7 +1192,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>751</width> <width>751</width>
<height>21</height> <height>23</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuHelp" > <widget class="QMenu" name="menuHelp" >
@ -1305,6 +1305,10 @@
<property name="title" > <property name="title" >
<string>P&amp;lugins</string> <string>P&amp;lugins</string>
</property> </property>
<property name="icon" >
<iconset resource="../icons.qrc" >
<normaloff>:/icons/preferences-plugin.png</normaloff>:/icons/preferences-plugin.png</iconset>
</property>
<widget class="QMenu" name="menuStartup" > <widget class="QMenu" name="menuStartup" >
<property name="title" > <property name="title" >
<string>Startup</string> <string>Startup</string>
@ -1337,9 +1341,9 @@
<property name="geometry" > <property name="geometry" >
<rect> <rect>
<x>0</x> <x>0</x>
<y>481</y> <y>482</y>
<width>751</width> <width>751</width>
<height>21</height> <height>20</height>
</rect> </rect>
</property> </property>
<property name="sizeGripEnabled" > <property name="sizeGripEnabled" >
@ -1353,9 +1357,9 @@
<property name="geometry" > <property name="geometry" >
<rect> <rect>
<x>0</x> <x>0</x>
<y>21</y> <y>23</y>
<width>751</width> <width>751</width>
<height>42</height> <height>46</height>
</rect> </rect>
</property> </property>
<property name="orientation" > <property name="orientation" >
@ -1567,10 +1571,10 @@
<action name="actionStarthere" > <action name="actionStarthere" >
<property name="icon" > <property name="icon" >
<iconset resource="../icons.qrc" > <iconset resource="../icons.qrc" >
<normaloff>:/icons/go-home.png</normaloff>:/icons/go-home.png</iconset> <normaloff>:/icons/help.png</normaloff>:/icons/help.png</iconset>
</property> </property>
<property name="text" > <property name="text" >
<string>&amp;Start Here...</string> <string>Documentation</string>
</property> </property>
</action> </action>
<action name="actionReportbug" > <action name="actionReportbug" >
@ -1850,7 +1854,7 @@
<action name="actionGetMoreDecks" > <action name="actionGetMoreDecks" >
<property name="icon" > <property name="icon" >
<iconset resource="../icons.qrc" > <iconset resource="../icons.qrc" >
<normaloff>:/icons/khtml_kget.png</normaloff>:/icons/khtml_kget.png</iconset> <normaloff>:/icons/download.png</normaloff>:/icons/download.png</iconset>
</property> </property>
<property name="text" > <property name="text" >
<string>&amp;Get More Decks...</string> <string>&amp;Get More Decks...</string>

View file

@ -1,5 +1,8 @@
<RCC> <RCC>
<qresource prefix="/" > <qresource prefix="/" >
<file>icons/download.png</file>
<file>icons/preferences-plugin.png</file>
<file>icons/system-software-update.png</file>
<file>icons/media-playback-stop.png</file> <file>icons/media-playback-stop.png</file>
<file>icons/media-record.png</file> <file>icons/media-record.png</file>
<file>icons/view-calendar-tasks.png</file> <file>icons/view-calendar-tasks.png</file>

BIN
icons/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB