diff --git a/aqt/browser.py b/aqt/browser.py
index f167a7b37..ae4f0439e 100644
--- a/aqt/browser.py
+++ b/aqt/browser.py
@@ -513,6 +513,9 @@ class Browser(QMainWindow):
self.setTabOrder(self.form.searchEdit, self.form.tableView)
self.form.searchEdit.setCompleter(None)
self.form.searchEdit.addItems(self.mw.pm.profile['searchHistory'])
+ self.connect(self.form.searchEdit.lineEdit(),
+ SIGNAL("returnPressed()"),
+ self.onSearch)
def onSearch(self, reset=True):
"Careful: if reset is true, the current note is saved."
@@ -753,6 +756,7 @@ by clicking on one on the left."""))
self.form.tree.clear()
root = self.form.tree
self._systemTagTree(root)
+ self._favTree(root)
self._decksTree(root)
self._modelTree(root)
self._userTagTree(root)
@@ -815,6 +819,18 @@ by clicking on one on the left."""))
item.setIcon(0, QIcon(":/icons/" + icon))
return root
+ 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 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()):
if t.lower() == "marked" or t.lower() == "leech":
@@ -1723,3 +1739,87 @@ a { margin-right: 1em; }
self.browser.addTags()
elif l == "deletetag":
self.browser.deleteTags()
+
+
+# Favourites button
+######################################################################
+class FavouritesLineEdit(QLineEdit):
+ buttonClicked = pyqtSignal(bool)
+
+ def __init__(self, mw, browser, parent=None):
+ super(FavouritesLineEdit, self).__init__(parent)
+ self.mw = mw
+ self.browser = browser
+ # add conf if missing
+ if not self.mw.col.conf.has_key('savedFilters'):
+ 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.connect(self, SIGNAL("textEdited(QString)"), 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)
+ super(FavouritesLineEdit, self).resizeEvent(event)
+
+ def setIcon(self, path):
+ self.button.setIcon(QIcon(path))
+
+ def setText(self, txt):
+ super(FavouritesLineEdit, self).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 = unicode(self.text()).strip()
+ for key, value in 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 = unicode(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.updateButton()
+ self.browser.setupTree()
+
+ 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.updateButton()
+ self.browser.setupTree()
diff --git a/designer/icons.qrc b/designer/icons.qrc
index cb3e36bd2..efcff2268 100644
--- a/designer/icons.qrc
+++ b/designer/icons.qrc
@@ -35,6 +35,8 @@
icons/editclear.png
icons/view-statistics.png
icons/emblem-favorite.png
+ icons/emblem-favorite-dark.png
+ icons/emblem-favorite-off.png
icons/view-pim-calendar.png
icons/anki-tag.png
icons/edit-redo.png
diff --git a/designer/icons/emblem-favorite-dark.png b/designer/icons/emblem-favorite-dark.png
new file mode 100644
index 000000000..740209965
Binary files /dev/null and b/designer/icons/emblem-favorite-dark.png differ
diff --git a/designer/icons/emblem-favorite-off.png b/designer/icons/emblem-favorite-off.png
new file mode 100644
index 000000000..b7fdbbd0d
Binary files /dev/null and b/designer/icons/emblem-favorite-off.png differ