mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
remove sidebar in browser
use a pop-up menu instead, which saves a lot of screen real estate and should be more intuitive for new users also: - add options to manage note types and clear unused tags in the relevant submenus - shuffle a few shortcut keys - remove the old favourites code - saving and removing now done via the menu - individual card templates now searchable
This commit is contained in:
parent
0c3565228d
commit
2415611450
2 changed files with 360 additions and 402 deletions
374
aqt/browser.py
374
aqt/browser.py
|
@ -17,7 +17,8 @@ from anki.utils import fmtTimeSpan, ids2str, stripHTMLMedia, htmlToTextLine, isW
|
|||
isMac, isLin
|
||||
from aqt.utils import saveGeom, restoreGeom, saveSplitter, restoreSplitter, \
|
||||
saveHeader, restoreHeader, saveState, restoreState, applyStyles, getTag, \
|
||||
showInfo, askUser, tooltip, openHelp, showWarning, shortcut, mungeQA
|
||||
showInfo, askUser, tooltip, openHelp, showWarning, shortcut, mungeQA, \
|
||||
getOnlyText
|
||||
from anki.hooks import runHook, addHook, remHook
|
||||
from aqt.webview import AnkiWebView
|
||||
from anki.consts import *
|
||||
|
@ -367,15 +368,12 @@ class Browser(QMainWindow):
|
|||
self.form.setupUi(self)
|
||||
restoreGeom(self, "editor", 0)
|
||||
restoreState(self, "editor")
|
||||
restoreSplitter(self.form.splitter_2, "editor2")
|
||||
restoreSplitter(self.form.splitter, "editor3")
|
||||
self.form.splitter_2.setChildrenCollapsible(False)
|
||||
self.form.splitter.setChildrenCollapsible(False)
|
||||
self.card = None
|
||||
self.setupColumns()
|
||||
self.setupTable()
|
||||
self.setupMenus()
|
||||
self.setupTree()
|
||||
self.setupHeaders()
|
||||
self.setupHooks()
|
||||
self.setupEditor()
|
||||
|
@ -390,6 +388,8 @@ class Browser(QMainWindow):
|
|||
f.previewButton.clicked.connect(self.onTogglePreview)
|
||||
f.previewButton.setToolTip(_("Preview Selected Card (%s)") %
|
||||
shortcut(_("Ctrl+Shift+P")))
|
||||
|
||||
f.filter.clicked.connect(self.onFilterButton)
|
||||
# edit
|
||||
f.actionUndo.triggered.connect(self.mw.onUndo)
|
||||
f.actionInvertSelection.triggered.connect(self.invertSelection)
|
||||
|
@ -400,7 +400,6 @@ class Browser(QMainWindow):
|
|||
f.actionAdd.triggered.connect(self.mw.onAddCard)
|
||||
f.actionAdd_Tags.triggered.connect(lambda: self.addTags())
|
||||
f.actionRemove_Tags.triggered.connect(lambda: self.deleteTags())
|
||||
f.actionClear_Unused_Tags.triggered.connect(self.clearUnusedTags)
|
||||
f.actionChangeModel.triggered.connect(self.onChangeModel)
|
||||
f.actionFindDuplicates.triggered.connect(self.onFindDupes)
|
||||
f.actionFindReplace.triggered.connect(self.onFindReplace)
|
||||
|
@ -419,7 +418,7 @@ class Browser(QMainWindow):
|
|||
f.actionLastCard.triggered.connect(self.onLastCard)
|
||||
f.actionFind.triggered.connect(self.onFind)
|
||||
f.actionNote.triggered.connect(self.onNote)
|
||||
f.actionTags.triggered.connect(self.onTags)
|
||||
f.actionTags.triggered.connect(self.onFilterButton)
|
||||
f.actionCardList.triggered.connect(self.onCardList)
|
||||
# help
|
||||
f.actionGuide.triggered.connect(self.onHelp)
|
||||
|
@ -465,7 +464,6 @@ class Browser(QMainWindow):
|
|||
def _closeEventCleanup(self):
|
||||
self._cancelPreviewTimer()
|
||||
self.editor.setNote(None)
|
||||
saveSplitter(self.form.splitter_2, "editor2")
|
||||
saveSplitter(self.form.splitter, "editor3")
|
||||
saveGeom(self, "editor")
|
||||
saveState(self, "editor")
|
||||
|
@ -484,10 +482,6 @@ class Browser(QMainWindow):
|
|||
"Show answer on RET or register answer."
|
||||
if evt.key() == Qt.Key_Escape:
|
||||
self.close()
|
||||
elif self.mw.app.focusWidget() == self.form.tree:
|
||||
if evt.key() in (Qt.Key_Return, Qt.Key_Enter):
|
||||
item = self.form.tree.currentItem()
|
||||
self.onTreeClick(item, 0)
|
||||
|
||||
def setupColumns(self):
|
||||
self.columns = [
|
||||
|
@ -513,7 +507,6 @@ class Browser(QMainWindow):
|
|||
######################################################################
|
||||
|
||||
def setupSearch(self):
|
||||
self.form.searchEdit.setLineEdit(FavouritesLineEdit(self.mw, self))
|
||||
self.form.searchButton.clicked.connect(self.onSearchActivated)
|
||||
self.form.searchEdit.lineEdit().returnPressed.connect(self.onSearchActivated)
|
||||
self.form.searchEdit.setCompleter(None)
|
||||
|
@ -742,40 +735,23 @@ by clicking on one on the left."""))
|
|||
# Filter tree
|
||||
######################################################################
|
||||
|
||||
class CallbackItem(QTreeWidgetItem):
|
||||
def __init__(self, root, name, onclick, oncollapse=None, expanded=False):
|
||||
QTreeWidgetItem.__init__(self, root, [name])
|
||||
self.setExpanded(expanded)
|
||||
self.onclick = onclick
|
||||
self.oncollapse = oncollapse
|
||||
def onFilterButton(self):
|
||||
m = QMenu()
|
||||
|
||||
def setupTree(self):
|
||||
self.form.tree.itemClicked.connect(self.onTreeClick)
|
||||
p = QPalette()
|
||||
p.setColor(QPalette.Base, QColor("#d6dde0"))
|
||||
self.form.tree.setPalette(p)
|
||||
self.buildTree()
|
||||
self.form.tree.itemExpanded.connect(lambda item: self.onTreeCollapse(item))
|
||||
self.form.tree.itemCollapsed.connect(lambda item: self.onTreeCollapse(item))
|
||||
self._addCommonFilters(m)
|
||||
m.addSeparator()
|
||||
|
||||
def buildTree(self):
|
||||
self.form.tree.clear()
|
||||
root = self.form.tree
|
||||
self._systemTagTree(root)
|
||||
self._favTree(root)
|
||||
self._decksTree(root)
|
||||
self._modelTree(root)
|
||||
self._userTagTree(root)
|
||||
self.form.tree.setIndentation(15)
|
||||
self._addTodayFilters(m)
|
||||
self._addCardStateFilters(m)
|
||||
m.addSeparator()
|
||||
|
||||
def onTreeClick(self, item, col):
|
||||
if getattr(item, 'onclick', None):
|
||||
item.onclick()
|
||||
self._addDeckFilters(m)
|
||||
self._addNoteTypeFilters(m)
|
||||
self._addTagFilters(m)
|
||||
self._addSavedSearches(m)
|
||||
|
||||
m.exec_(self.form.filter.mapToGlobal(QPoint(0,0)))
|
||||
|
||||
def onTreeCollapse(self, item):
|
||||
if getattr(item, 'oncollapse', None):
|
||||
item.oncollapse()
|
||||
|
||||
def setFilter(self, *args):
|
||||
if len(args) == 1:
|
||||
txt = args[0]
|
||||
|
@ -805,71 +781,172 @@ by clicking on one on the left."""))
|
|||
self.form.searchEdit.lineEdit().setText(txt)
|
||||
self.onSearchActivated()
|
||||
|
||||
def _systemTagTree(self, root):
|
||||
tags = (
|
||||
(_("Whole Collection"), "ankibw", ""),
|
||||
(_("Current Deck"), "deck16", "deck:current"),
|
||||
(_("Added Today"), "view-pim-calendar.png", "added:1"),
|
||||
(_("Studied Today"), "view-pim-calendar.png", "rated:1"),
|
||||
(_("Again Today"), "view-pim-calendar.png", "rated:1:1"),
|
||||
(_("New"), "plus16.png", "is:new"),
|
||||
(_("Learning"), "stock_new_template_red.png", "is:learn"),
|
||||
(_("Review"), "clock16.png", "is:review"),
|
||||
(_("Due"), "clock16.png", "is:due"),
|
||||
(_("Marked"), "star16.png", "tag:marked"),
|
||||
(_("Suspended"), "media-playback-pause.png", "is:suspended"),
|
||||
(_("Leech"), "emblem-important.png", "tag:leech"))
|
||||
for name, icon, cmd in tags:
|
||||
item = self.CallbackItem(
|
||||
root, name, lambda c=cmd: self.setFilter(c))
|
||||
item.setIcon(0, QIcon(":/icons/" + icon))
|
||||
return root
|
||||
def _addSimpleFilters(self, m, items):
|
||||
for row in items:
|
||||
if row is None:
|
||||
m.addSeparator()
|
||||
else:
|
||||
label, search = row
|
||||
a = m.addAction(label)
|
||||
a.triggered.connect(lambda *, f=search: self.setFilter(f))
|
||||
|
||||
def _favTree(self, root):
|
||||
saved = self.col.conf.get('savedFilters', [])
|
||||
if not saved:
|
||||
# Don't add favourites to tree if none saved
|
||||
return
|
||||
root = self.CallbackItem(root, _("My Searches"), None)
|
||||
root.setExpanded(True)
|
||||
root.setIcon(0, QIcon(":/icons/emblem-favorite-dark.png"))
|
||||
for name, filt in sorted(saved.items()):
|
||||
item = self.CallbackItem(root, name, lambda s=filt: self.setFilter(s))
|
||||
item.setIcon(0, QIcon(":/icons/emblem-favorite-dark.png"))
|
||||
|
||||
def _userTagTree(self, root):
|
||||
for t in sorted(self.col.tags.all()):
|
||||
def _addCommonFilters(self, m):
|
||||
items = (
|
||||
(_("Whole Collection"), ""),
|
||||
(_("Current Deck"), "deck:current"),
|
||||
None,
|
||||
(_("Marked"), "tag:marked"),
|
||||
(_("Leech"), "tag:leech"))
|
||||
self._addSimpleFilters(m, items)
|
||||
|
||||
def _addTodayFilters(self, m):
|
||||
m = m.addMenu(_("Today"))
|
||||
items = (
|
||||
(_("Added Today"), "added:1"),
|
||||
(_("Studied Today"), "rated:1"),
|
||||
(_("Again Today"), "rated:1:1"))
|
||||
self._addSimpleFilters(m, items)
|
||||
|
||||
def _addCardStateFilters(self, m):
|
||||
m = m.addMenu(_("Card State"))
|
||||
items = (
|
||||
(_("New"), "is:new"),
|
||||
(_("Learning"), "is:learn"),
|
||||
(_("Review"), "is:review"),
|
||||
(_("Due"), "is:due"),
|
||||
None,
|
||||
(_("Suspended"), "is:suspended"),
|
||||
(_("Buried"), "is:buried"))
|
||||
self._addSimpleFilters(m, items)
|
||||
|
||||
_tagsMenuSize = 30
|
||||
|
||||
def _addTagFilters(self, m):
|
||||
m = m.addMenu(_("Tags"))
|
||||
|
||||
a = m.addAction(_("Clear Unused"))
|
||||
a.triggered.connect(self.clearUnusedTags)
|
||||
m.addSeparator()
|
||||
|
||||
tags = sorted(self.col.tags.all(), key=lambda s: s.lower())
|
||||
|
||||
if len(tags) < self._tagsMenuSize:
|
||||
self._addTagFilterBlock(m, tags)
|
||||
else:
|
||||
# split the list into a more manageable size
|
||||
chunks = []
|
||||
while tags:
|
||||
chunk = tags[:self._tagsMenuSize]
|
||||
chunks.append(chunk)
|
||||
del tags[:self._tagsMenuSize]
|
||||
# use separate menu for each chunk
|
||||
for chunk in chunks:
|
||||
name = chunk[0]+"..."
|
||||
child = m.addMenu(name)
|
||||
self._addTagFilterBlock(child, chunk)
|
||||
|
||||
def _addTagFilterBlock(self, m, tags):
|
||||
for t in tags:
|
||||
if t.lower() == "marked" or t.lower() == "leech":
|
||||
continue
|
||||
item = self.CallbackItem(
|
||||
root, t, lambda t=t: self.setFilter("tag", t))
|
||||
item.setIcon(0, QIcon(":/icons/anki-tag.png"))
|
||||
a = m.addAction(t)
|
||||
a.triggered.connect(lambda *, tag=t: self.setFilter("tag", tag))
|
||||
|
||||
def _decksTree(self, root):
|
||||
grps = self.col.sched.deckDueTree()
|
||||
def fillGroups(root, grps, head=""):
|
||||
for g in grps:
|
||||
item = self.CallbackItem(
|
||||
root, g[0],
|
||||
lambda g=g: self.setFilter("deck", head+g[0]),
|
||||
lambda g=g: self.mw.col.decks.collapseBrowser(g[1]),
|
||||
not self.mw.col.decks.get(g[1]).get('browserCollapsed', False))
|
||||
item.setIcon(0, QIcon(":/icons/deck16.png"))
|
||||
newhead = head + g[0]+"::"
|
||||
fillGroups(item, g[5], newhead)
|
||||
fillGroups(root, grps)
|
||||
def _addDeckFilters(self, m):
|
||||
def addDecks(parent, decks):
|
||||
for head, did, rev, lrn, new, children in decks:
|
||||
name = self.mw.col.decks.get(did)['name']
|
||||
shortname = name.split("::")[-1]
|
||||
if children:
|
||||
newparent = parent.addMenu(shortname)
|
||||
a = newparent.addAction(_("Filter"))
|
||||
a.triggered.connect(
|
||||
lambda *, name=name: self.setFilter("deck", name))
|
||||
newparent.addSeparator()
|
||||
addDecks(newparent, children)
|
||||
else:
|
||||
a = parent.addAction(shortname)
|
||||
a.triggered.connect(
|
||||
lambda *, name=name: self.setFilter("deck", name))
|
||||
|
||||
def _modelTree(self, root):
|
||||
for m in sorted(self.col.models.all(), key=itemgetter("name")):
|
||||
mitem = self.CallbackItem(
|
||||
root, m['name'], lambda m=m: self.setFilter("mid", str(m['id'])))
|
||||
mitem.setIcon(0, QIcon(":/icons/product_design.png"))
|
||||
# for t in m['tmpls']:
|
||||
# titem = self.CallbackItem(
|
||||
# t['name'], lambda m=m, t=t: self.setFilter(
|
||||
# "model", m['name'], "card", t['name']))
|
||||
# titem.setIcon(0, QIcon(":/icons/stock_new_template.png"))
|
||||
# mitem.addChild(titem)
|
||||
# fixme: could rewrite to avoid calculating due # in the future
|
||||
alldecks = self.col.sched.deckDueTree()
|
||||
root = m.addMenu(_("Decks"))
|
||||
|
||||
addDecks(root, alldecks)
|
||||
|
||||
def _addNoteTypeFilters(self, m):
|
||||
m = m.addMenu(_("Note Types"))
|
||||
a = m.addAction(_("Manage..."))
|
||||
a.triggered.connect(self.mw.onNoteTypes)
|
||||
m.addSeparator()
|
||||
for nt in sorted(self.col.models.all(), key=itemgetter("name")):
|
||||
# no sub menu if it's a single template
|
||||
if len(nt['tmpls']) == 1:
|
||||
a = m.addAction(nt['name'])
|
||||
a.triggered.connect(lambda *, nt=nt: self.setFilter("mid", str(nt['id'])))
|
||||
else:
|
||||
subm = m.addMenu(nt['name'])
|
||||
a = subm.addAction(_("All Card Types"))
|
||||
a.triggered.connect(lambda *, nt=nt: self.setFilter("mid", str(nt['id'])))
|
||||
|
||||
# add templates
|
||||
subm.addSeparator()
|
||||
for c, tmpl in enumerate(nt['tmpls']):
|
||||
a = subm.addAction(_("%(n)d: %(name)s") % dict(
|
||||
n=c+1, name=tmpl['name']))
|
||||
a.triggered.connect(lambda *, nt=nt, c=c: self.setFilter(
|
||||
"mid", str(nt['id']), "card", str(c+1)
|
||||
))
|
||||
|
||||
# Favourites
|
||||
######################################################################
|
||||
|
||||
def _addSavedSearches(self, m):
|
||||
# make sure exists
|
||||
if "savedFilters" not in self.col.conf:
|
||||
self.col.conf['savedFilters'] = {}
|
||||
|
||||
m.addSeparator()
|
||||
|
||||
if self._currentFilterIsSaved():
|
||||
a = m.addAction(_("Remove Current Filter..."))
|
||||
a.triggered.connect(self._onRemoveFilter)
|
||||
else:
|
||||
a = m.addAction(_("Save Current Filter..."))
|
||||
a.triggered.connect(self._onSaveFilter)
|
||||
|
||||
saved = self.col.conf['savedFilters']
|
||||
if not saved:
|
||||
return
|
||||
|
||||
m.addSeparator()
|
||||
for name, filt in sorted(saved.items()):
|
||||
a = m.addAction(name)
|
||||
a.triggered.connect(lambda *, f=filt: self.setFilter(f))
|
||||
|
||||
def _onSaveFilter(self):
|
||||
name = getOnlyText(_("Please give your filter a name:"))
|
||||
if not name:
|
||||
return
|
||||
filt = self.form.searchEdit.lineEdit().text()
|
||||
self.col.conf['savedFilters'][name] = filt
|
||||
self.col.setMod()
|
||||
|
||||
def _onRemoveFilter(self):
|
||||
name = self._currentFilterIsSaved()
|
||||
if not askUser(_("Remove %s from your saved searches?") % name):
|
||||
return
|
||||
del self.col.conf['savedFilters'][name]
|
||||
self.col.setMod()
|
||||
|
||||
# returns name if found
|
||||
def _currentFilterIsSaved(self):
|
||||
filt = self.form.searchEdit.lineEdit().text()
|
||||
for k,v in self.col.conf['savedFilters'].items():
|
||||
if filt == v:
|
||||
return k
|
||||
return None
|
||||
|
||||
# Info
|
||||
######################################################################
|
||||
|
@ -1261,7 +1338,6 @@ update cards set usn=?, mod=?, did=? where id in """ + scids,
|
|||
|
||||
def _clearUnusedTags(self):
|
||||
self.col.tags.registerNotes()
|
||||
self.buildTree()
|
||||
|
||||
# Suspending and marking
|
||||
######################################################################
|
||||
|
@ -1385,16 +1461,12 @@ update cards set usn=?, mod=?, did=? where id in """ + scids,
|
|||
addHook("reset", self.onReset)
|
||||
addHook("editTimer", self.refreshCurrentCard)
|
||||
addHook("editFocusLost", self.refreshCurrentCardFilter)
|
||||
for t in "newTag", "newModel", "newDeck":
|
||||
addHook(t, self.buildTree)
|
||||
|
||||
def teardownHooks(self):
|
||||
remHook("reset", self.onReset)
|
||||
remHook("editTimer", self.refreshCurrentCard)
|
||||
remHook("editFocusLost", self.refreshCurrentCardFilter)
|
||||
remHook("undoState", self.onUndoState)
|
||||
for t in "newTag", "newModel", "newDeck":
|
||||
remHook(t, self.buildTree)
|
||||
|
||||
def onUndoState(self, on):
|
||||
self.form.actionUndo.setEnabled(on)
|
||||
|
@ -1590,9 +1662,6 @@ update cards set usn=?, mod=?, did=? where id in """ + scids,
|
|||
self.editor.web.setFocus()
|
||||
self.editor.web.eval("focusField(0);")
|
||||
|
||||
def onTags(self):
|
||||
self.form.tree.setFocus()
|
||||
|
||||
def onCardList(self):
|
||||
self.form.tableView.setFocus()
|
||||
|
||||
|
@ -1774,88 +1843,3 @@ Are you sure you want to continue?""")):
|
|||
def onHelp(self):
|
||||
openHelp("browsermisc")
|
||||
|
||||
# Favourites button
|
||||
######################################################################
|
||||
class FavouritesLineEdit(QLineEdit):
|
||||
buttonClicked = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, mw, browser, parent=None):
|
||||
super().__init__(parent)
|
||||
self.mw = mw
|
||||
self.browser = browser
|
||||
# add conf if missing
|
||||
if 'savedFilters' not in self.mw.col.conf:
|
||||
self.mw.col.conf['savedFilters'] = {}
|
||||
self.button = QToolButton(self)
|
||||
self.button.setStyleSheet('border: 0px;')
|
||||
self.button.setCursor(Qt.ArrowCursor)
|
||||
self.button.clicked.connect(self.buttonClicked.emit)
|
||||
self.setIcon(':/icons/emblem-favorite-off.png')
|
||||
# flag to raise save or delete dialog on button click
|
||||
self.doSave = True
|
||||
# name of current saved filter (if query matches)
|
||||
self.name = None
|
||||
self.buttonClicked.connect(self.onClicked)
|
||||
self.textChanged.connect(self.updateButton)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
buttonSize = self.button.sizeHint()
|
||||
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
|
||||
self.button.move(self.rect().right() - frameWidth - buttonSize.width(),
|
||||
(self.rect().bottom() - buttonSize.height() + 1) / 2)
|
||||
self.setTextMargins(0, 0, buttonSize.width() * 1.5, 0)
|
||||
super().resizeEvent(event)
|
||||
|
||||
def setIcon(self, path):
|
||||
self.button.setIcon(QIcon(path))
|
||||
|
||||
def setText(self, txt):
|
||||
super().setText(txt)
|
||||
self.updateButton()
|
||||
|
||||
def updateButton(self, reset=True):
|
||||
# If search text is a saved query, switch to the delete button.
|
||||
# Otherwise show save button.
|
||||
txt = str(self.text()).strip()
|
||||
for key, value in list(self.mw.col.conf['savedFilters'].items()):
|
||||
if txt == value:
|
||||
self.doSave = False
|
||||
self.name = key
|
||||
self.setIcon(QIcon(":/icons/emblem-favorite.png"))
|
||||
return
|
||||
self.doSave = True
|
||||
self.setIcon(QIcon(":/icons/emblem-favorite-off.png"))
|
||||
|
||||
def onClicked(self):
|
||||
if self.doSave:
|
||||
self.saveClicked()
|
||||
else:
|
||||
self.deleteClicked()
|
||||
|
||||
def saveClicked(self):
|
||||
txt = str(self.text()).strip()
|
||||
dlg = QInputDialog(self)
|
||||
dlg.setInputMode(QInputDialog.TextInput)
|
||||
dlg.setLabelText(_("The current search terms will be added as a new "
|
||||
"item in the sidebar.\n"
|
||||
"Search name:"))
|
||||
dlg.setWindowTitle(_("Save search"))
|
||||
ok = dlg.exec_()
|
||||
name = dlg.textValue()
|
||||
if ok:
|
||||
self.mw.col.conf['savedFilters'][name] = txt
|
||||
self.mw.col.setMod()
|
||||
|
||||
self.updateButton()
|
||||
self.browser.buildTree()
|
||||
|
||||
def deleteClicked(self):
|
||||
msg = _('Remove "%s" from your saved searches?') % self.name
|
||||
ok = QMessageBox.question(self, _('Remove search'),
|
||||
msg, QMessageBox.Yes, QMessageBox.No)
|
||||
|
||||
if ok == QMessageBox.Yes:
|
||||
self.mw.col.conf['savedFilters'].pop(self.name, None)
|
||||
self.mw.col.setMod()
|
||||
self.updateButton()
|
||||
self.browser.buildTree()
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<height>400</height>
|
||||
<height>493</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
|
@ -26,210 +26,193 @@
|
|||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>4</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="tree">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</column>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="searchEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>9</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="searchButton">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="previewButton">
|
||||
<property name="text">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+P</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="filter">
|
||||
<property name="text">
|
||||
<string>Filter...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>9</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>4</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="searchEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>9</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="searchButton">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="previewButton">
|
||||
<property name="text">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+P</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>9</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="fieldsArea" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="fieldsArea" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -297,7 +280,6 @@
|
|||
<addaction name="separator"/>
|
||||
<addaction name="actionAdd_Tags"/>
|
||||
<addaction name="actionRemove_Tags"/>
|
||||
<addaction name="actionClear_Unused_Tags"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionChangeModel"/>
|
||||
<addaction name="separator"/>
|
||||
|
@ -324,7 +306,7 @@
|
|||
<string>Select &All</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
<string>Ctrl+Alt+A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUndo">
|
||||
|
@ -353,7 +335,7 @@
|
|||
<string>N&ote</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+F</string>
|
||||
<string>Ctrl+Shift+N</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNextCard">
|
||||
|
@ -392,9 +374,6 @@
|
|||
<property name="text">
|
||||
<string>Select &Notes</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+N</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFindReplace">
|
||||
<property name="text">
|
||||
|
@ -411,10 +390,10 @@
|
|||
</action>
|
||||
<action name="actionTags">
|
||||
<property name="text">
|
||||
<string>Fil&ters</string>
|
||||
<string>Fil&ter</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+R</string>
|
||||
<string>Ctrl+Shift+F</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCardList">
|
||||
|
@ -486,11 +465,6 @@
|
|||
<string>Ctrl+Shift+D</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClear_Unused_Tags">
|
||||
<property name="text">
|
||||
<string>Clear Unused Tags</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToggle_Suspend">
|
||||
<property name="text">
|
||||
<string>Toggle Suspend</string>
|
||||
|
|
Loading…
Reference in a new issue