mirror of
https://github.com/ankitects/anki.git
synced 2025-11-11 07:07:13 -05:00
more column work
- removed sort area; users can click on columns to sort now - displayed columns are now loaded/saved from deck
This commit is contained in:
parent
4b1d377a40
commit
82be9a432e
4 changed files with 101 additions and 123 deletions
155
aqt/browser.py
155
aqt/browser.py
|
|
@ -36,7 +36,8 @@ class DeckModel(QAbstractTableModel):
|
||||||
self.browser = browser
|
self.browser = browser
|
||||||
self.deck = browser.deck
|
self.deck = browser.deck
|
||||||
self.sortKey = None
|
self.sortKey = None
|
||||||
self.columns = ["question", "answer", "sortField", "cardDue", "cardEase"]
|
self.activeCols = self.deck.conf.get(
|
||||||
|
"activeCols", ["factFld", "answer", "cardDue", "cardEase"])
|
||||||
self.cards = []
|
self.cards = []
|
||||||
self.cardObjs = {}
|
self.cardObjs = {}
|
||||||
|
|
||||||
|
|
@ -53,7 +54,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 len(self.activeCols)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
|
|
@ -77,12 +78,7 @@ class DeckModel(QAbstractTableModel):
|
||||||
return QVariant()
|
return QVariant()
|
||||||
elif role == Qt.DisplayRole:
|
elif role == Qt.DisplayRole:
|
||||||
type = self.columnType(section)
|
type = self.columnType(section)
|
||||||
if type == "question":
|
for stype, name in self.browser.columns:
|
||||||
txt = _("Question")
|
|
||||||
elif type == "answer":
|
|
||||||
txt = _("Answer")
|
|
||||||
else:
|
|
||||||
for stype, name in self.browser.sortTypes:
|
|
||||||
if type == stype:
|
if type == stype:
|
||||||
txt = name
|
txt = name
|
||||||
break
|
break
|
||||||
|
|
@ -117,11 +113,7 @@ class DeckModel(QAbstractTableModel):
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def columnType(self, column):
|
def columnType(self, column):
|
||||||
type = self.columns[column]
|
type = self.activeCols[column]
|
||||||
if type == "sortField":
|
|
||||||
type = self.deck.conf['sortType']
|
|
||||||
if type == "factFld":
|
|
||||||
type = "cardDue"
|
|
||||||
return type
|
return type
|
||||||
|
|
||||||
def columnData(self, index):
|
def columnData(self, index):
|
||||||
|
|
@ -133,7 +125,10 @@ class DeckModel(QAbstractTableModel):
|
||||||
return self.formatQA(c.q())
|
return self.formatQA(c.q())
|
||||||
elif type == "answer":
|
elif type == "answer":
|
||||||
return self.formatQA(c.a())
|
return self.formatQA(c.a())
|
||||||
elif type == "factFld" or type == "cardDue":
|
elif type == "factFld":
|
||||||
|
f = c.fact()
|
||||||
|
return self.formatQA(f._fields[f.model().sortIdx()])
|
||||||
|
elif type == "cardDue":
|
||||||
return self.nextDue(c, index)
|
return self.nextDue(c, index)
|
||||||
elif type == "factCrt":
|
elif type == "factCrt":
|
||||||
return time.strftime("%Y-%m-%d", time.localtime(c.fact().crt))
|
return time.strftime("%Y-%m-%d", time.localtime(c.fact().crt))
|
||||||
|
|
@ -233,7 +228,7 @@ class Browser(QMainWindow):
|
||||||
restoreSplitter(self.form.splitter_3, "editor3")
|
restoreSplitter(self.form.splitter_3, "editor3")
|
||||||
self.form.splitter_2.setChildrenCollapsible(False)
|
self.form.splitter_2.setChildrenCollapsible(False)
|
||||||
self.form.splitter_3.setChildrenCollapsible(False)
|
self.form.splitter_3.setChildrenCollapsible(False)
|
||||||
self.setupSort()
|
self.setupColumns()
|
||||||
self.setupToolbar()
|
self.setupToolbar()
|
||||||
self.setupTable()
|
self.setupTable()
|
||||||
self.setupMenus()
|
self.setupMenus()
|
||||||
|
|
@ -243,7 +238,6 @@ class Browser(QMainWindow):
|
||||||
self.setupHooks()
|
self.setupHooks()
|
||||||
self.setupEditor()
|
self.setupEditor()
|
||||||
self.setupCardInfo()
|
self.setupCardInfo()
|
||||||
self.updateSortIcon()
|
|
||||||
self.updateFont()
|
self.updateFont()
|
||||||
self.form.searchEdit.setFocus()
|
self.form.searchEdit.setFocus()
|
||||||
self.updateFilterLabel()
|
self.updateFilterLabel()
|
||||||
|
|
@ -310,6 +304,7 @@ class Browser(QMainWindow):
|
||||||
saveGeom(self, "editor")
|
saveGeom(self, "editor")
|
||||||
saveState(self, "editor")
|
saveState(self, "editor")
|
||||||
saveHeader(self.form.tableView.horizontalHeader(), "editor")
|
saveHeader(self.form.tableView.horizontalHeader(), "editor")
|
||||||
|
self.deck.conf['activeCols'] = self.model.activeCols
|
||||||
self.hide()
|
self.hide()
|
||||||
aqt.dialogs.close("Browser")
|
aqt.dialogs.close("Browser")
|
||||||
self.teardownHooks()
|
self.teardownHooks()
|
||||||
|
|
@ -320,6 +315,21 @@ class Browser(QMainWindow):
|
||||||
if evt.key() in (Qt.Key_Escape,):
|
if evt.key() in (Qt.Key_Escape,):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
def setupColumns(self):
|
||||||
|
self.columns = [
|
||||||
|
('question', _("Question")),
|
||||||
|
('answer', _("Answer")),
|
||||||
|
('factFld', _("Sort Field")),
|
||||||
|
('factCrt', _("Creation date")),
|
||||||
|
('factMod', _("Edit date")),
|
||||||
|
('cardMod', _("Review date")),
|
||||||
|
('cardDue', _("Due date")),
|
||||||
|
('cardIvl', _("Card interval")),
|
||||||
|
('cardEase', _("Ease factor")),
|
||||||
|
('cardReps', _("Review count")),
|
||||||
|
('cardLapses', _("Lapse count")),
|
||||||
|
]
|
||||||
|
|
||||||
# Searching
|
# Searching
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|
@ -369,7 +379,7 @@ class Browser(QMainWindow):
|
||||||
|
|
||||||
def setupTable(self):
|
def setupTable(self):
|
||||||
self.model = DeckModel(self)
|
self.model = DeckModel(self)
|
||||||
self.form.tableView.setSortingEnabled(False)
|
self.form.tableView.setSortingEnabled(True)
|
||||||
self.form.tableView.setShowGrid(False)
|
self.form.tableView.setShowGrid(False)
|
||||||
self.form.tableView.setModel(self.model)
|
self.form.tableView.setModel(self.model)
|
||||||
self.form.tableView.selectionModel()
|
self.form.tableView.selectionModel()
|
||||||
|
|
@ -397,7 +407,6 @@ class Browser(QMainWindow):
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def focusCard(self):
|
def focusCard(self):
|
||||||
print "focus"
|
|
||||||
if self.card:
|
if self.card:
|
||||||
try:
|
try:
|
||||||
self.card.id
|
self.card.id
|
||||||
|
|
@ -414,7 +423,7 @@ class Browser(QMainWindow):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Headers
|
# Headers & sorting
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def setupHeaders(self):
|
def setupHeaders(self):
|
||||||
|
|
@ -424,80 +433,76 @@ class Browser(QMainWindow):
|
||||||
vh.hide()
|
vh.hide()
|
||||||
hh.show()
|
hh.show()
|
||||||
restoreHeader(hh, "editor")
|
restoreHeader(hh, "editor")
|
||||||
for i in range(2):
|
hh.setHighlightSections(False)
|
||||||
hh.setResizeMode(i, QHeaderView.Stretch)
|
hh.setMinimumSectionSize(50)
|
||||||
hh.setResizeMode(2, QHeaderView.Interactive)
|
self.setColumnSizes()
|
||||||
hh.setContextMenuPolicy(Qt.CustomContextMenu)
|
hh.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
hh.connect(hh, SIGNAL("customContextMenuRequested(QPoint)"),
|
hh.connect(hh, SIGNAL("customContextMenuRequested(QPoint)"),
|
||||||
self.onHeaderContext)
|
self.onHeaderContext)
|
||||||
|
hh.connect(hh, SIGNAL("sortIndicatorChanged(int, Qt::SortOrder)"),
|
||||||
|
self.onSortChanged)
|
||||||
|
self.setSortIndicator()
|
||||||
|
|
||||||
|
def onSortChanged(self, idx, ord):
|
||||||
|
type = self.model.activeCols[idx]
|
||||||
|
if type in ("question", "answer"):
|
||||||
|
type = "factFld"
|
||||||
|
if self.deck.conf['sortType'] != type:
|
||||||
|
self.deck.conf['sortType'] = type
|
||||||
|
# default to descending for non-text fields
|
||||||
|
if type not in ("question", "answer", "factFld"):
|
||||||
|
ord = not ord
|
||||||
|
self.deck.conf['sortBackwards'] = ord
|
||||||
|
self.model.showMatching()
|
||||||
|
# fixme: we do this in various locations
|
||||||
|
self.updateFilterLabel()
|
||||||
|
self.focusCard()
|
||||||
|
else:
|
||||||
|
self.deck.conf['sortBackwards'] = ord
|
||||||
|
self.model.cards.reverse()
|
||||||
|
self.setSortIndicator()
|
||||||
|
self.model.reset()
|
||||||
|
|
||||||
|
def setSortIndicator(self):
|
||||||
|
hh = self.form.tableView.horizontalHeader()
|
||||||
|
type = self.deck.conf['sortType']
|
||||||
|
if type not in self.model.activeCols:
|
||||||
|
hh.setSortIndicatorShown(False)
|
||||||
|
return
|
||||||
|
idx = self.model.activeCols.index(type)
|
||||||
|
if self.deck.conf['sortBackwards']:
|
||||||
|
ord = Qt.DescendingOrder
|
||||||
|
else:
|
||||||
|
ord = Qt.AscendingOrder
|
||||||
|
hh.setSortIndicator(idx, ord)
|
||||||
|
hh.setSortIndicatorShown(True)
|
||||||
|
|
||||||
def onHeaderContext(self, pos):
|
def onHeaderContext(self, pos):
|
||||||
gpos = self.form.tableView.mapToGlobal(pos)
|
gpos = self.form.tableView.mapToGlobal(pos)
|
||||||
m = QMenu()
|
m = QMenu()
|
||||||
for type, name in [("question", _("Question")),
|
for type, name in self.columns:
|
||||||
("answer", _("Answer")),
|
|
||||||
("sortField", _("Current Sort Field"))
|
|
||||||
] + self.sortTypes:
|
|
||||||
a = m.addAction(name)
|
a = m.addAction(name)
|
||||||
a.setCheckable(True)
|
a.setCheckable(True)
|
||||||
a.setChecked(type in self.model.columns)
|
a.setChecked(type in self.model.activeCols)
|
||||||
a.connect(a, SIGNAL("toggled(bool)"),
|
a.connect(a, SIGNAL("toggled(bool)"),
|
||||||
lambda b, t=type: self.toggleField(t))
|
lambda b, t=type: self.toggleField(t))
|
||||||
m.exec_(gpos)
|
m.exec_(gpos)
|
||||||
|
|
||||||
def toggleField(self, type):
|
def toggleField(self, type):
|
||||||
if type in self.model.columns:
|
if type in self.model.activeCols:
|
||||||
self.model.columns.remove(type)
|
self.model.activeCols.remove(type)
|
||||||
else:
|
else:
|
||||||
self.model.columns.append(type)
|
self.model.activeCols.append(type)
|
||||||
|
self.setColumnSizes()
|
||||||
self.model.reset()
|
self.model.reset()
|
||||||
|
|
||||||
# Sorting
|
def setColumnSizes(self):
|
||||||
######################################################################
|
hh = self.form.tableView.horizontalHeader()
|
||||||
|
for c, i in enumerate(self.model.activeCols):
|
||||||
def setupSort(self):
|
if i in ("question", "answer", "factFld"):
|
||||||
self.sortTypes = [
|
hh.setResizeMode(c, QHeaderView.Stretch)
|
||||||
('factFld', _("Fields")),
|
|
||||||
('factCrt', _("Creation date")),
|
|
||||||
('factMod', _("Edit date")),
|
|
||||||
('cardMod', _("Review date")),
|
|
||||||
('cardDue', _("Due date")),
|
|
||||||
('cardIvl', _("Card interval")),
|
|
||||||
('cardEase', _("Ease factor")),
|
|
||||||
('cardReps', _("Review count")),
|
|
||||||
('cardLapses', _("Lapse count")),
|
|
||||||
]
|
|
||||||
for c, (type, name) in enumerate(self.sortTypes):
|
|
||||||
self.form.sortBox.addItem(name)
|
|
||||||
if type == self.deck.conf['sortType']:
|
|
||||||
idx = c
|
|
||||||
self.form.sortBox.setCurrentIndex(idx)
|
|
||||||
self.connect(self.form.sortBox, SIGNAL("activated(int)"),
|
|
||||||
self.sortChanged)
|
|
||||||
self.sortChanged(idx, refresh=False)
|
|
||||||
self.connect(self.form.sortOrder, SIGNAL("clicked()"),
|
|
||||||
self.toggleSortOrder)
|
|
||||||
|
|
||||||
def toggleSortOrder(self):
|
|
||||||
self.deck.conf['sortBackwards'] = not self.deck.conf['sortBackwards']
|
|
||||||
self.model.cards.reverse()
|
|
||||||
self.model.reset()
|
|
||||||
self.focusCard()
|
|
||||||
self.updateSortIcon()
|
|
||||||
|
|
||||||
def updateSortIcon(self):
|
|
||||||
if self.deck.conf['sortBackwards']:
|
|
||||||
self.form.sortOrder.setIcon(QIcon(":/icons/view-sort-descending.png"))
|
|
||||||
else:
|
else:
|
||||||
self.form.sortOrder.setIcon(QIcon(":/icons/view-sort-ascending.png"))
|
hh.setResizeMode(c, QHeaderView.Interactive)
|
||||||
|
|
||||||
def sortChanged(self, idx, refresh=True):
|
|
||||||
self.deck.conf['sortType'] = self.sortTypes[idx][0]
|
|
||||||
if refresh:
|
|
||||||
self.model.showMatching()
|
|
||||||
# fixme: we do this in various locations
|
|
||||||
self.updateFilterLabel()
|
|
||||||
self.focusCard()
|
|
||||||
|
|
||||||
# Filter tree
|
# Filter tree
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ title="%s">%s</button>''' % (
|
||||||
self.form.centralwidget.setLayout(self.mainLayout)
|
self.form.centralwidget.setLayout(self.mainLayout)
|
||||||
addHook("undoEnd", self.maybeEnableUndo)
|
addHook("undoEnd", self.maybeEnableUndo)
|
||||||
if self.config['mainWindowState']:
|
if self.config['mainWindowState']:
|
||||||
restoreGeom(self, "mainWindow", 21)
|
restoreGeom(self, "mainWindow")
|
||||||
restoreState(self, "mainWindow")
|
restoreState(self, "mainWindow")
|
||||||
else:
|
else:
|
||||||
self.resize(500, 400)
|
self.resize(500, 400)
|
||||||
|
|
|
||||||
14
aqt/utils.py
14
aqt/utils.py
|
|
@ -234,13 +234,13 @@ def restoreGeom(widget, key, offset=None):
|
||||||
key += "Geom"
|
key += "Geom"
|
||||||
if aqt.mw.config.get(key):
|
if aqt.mw.config.get(key):
|
||||||
widget.restoreGeometry(aqt.mw.config[key])
|
widget.restoreGeometry(aqt.mw.config[key])
|
||||||
# if sys.platform.startswith("darwin") and offset:
|
if sys.platform.startswith("darwin") and offset:
|
||||||
# from aqt.main import QtConfig as q
|
from aqt.main import QtConfig as q
|
||||||
# minor = (q.qt_version & 0x00ff00) >> 8
|
minor = (q.qt_version & 0x00ff00) >> 8
|
||||||
# if minor > 6:
|
if minor > 6:
|
||||||
# # bug in osx toolkit
|
# bug in osx toolkit
|
||||||
# s = widget.size()
|
s = widget.size()
|
||||||
# widget.resize(s.width(), s.height()+offset*2)
|
widget.resize(s.width(), s.height()+offset*2)
|
||||||
|
|
||||||
def saveState(widget, key):
|
def saveState(widget, key):
|
||||||
key += "State"
|
key += "State"
|
||||||
|
|
|
||||||
|
|
@ -88,39 +88,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Sort:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QPushButton" name="sortOrder">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="icons.qrc">
|
|
||||||
<normaloff>:/icons/view-sort-ascending.png</normaloff>:/icons/view-sort-ascending.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="4">
|
|
||||||
<widget class="QComboBox" name="sortBox"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
@ -159,15 +126,21 @@
|
||||||
<property name="selectionBehavior">
|
<property name="selectionBehavior">
|
||||||
<enum>QAbstractItemView::SelectRows</enum>
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<attribute name="horizontalHeaderHighlightSections">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||||
|
<number>20</number>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="lowerWidget">
|
<widget class="QWidget" name="lowerWidget">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout2">
|
<layout class="QHBoxLayout" name="horizontalLayout2">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="fieldsArea" native="true">
|
<widget class="QWidget" name="fieldsArea" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue