From dbacc79d97ce0b0b42c3d559dbc3214400f64fa7 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 12 Jan 2011 09:45:50 +0000 Subject: [PATCH 1/5] Remove declarations of get_metadata cache counters --- src/calibre/library/database2.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index aa491aff28..d2654577b9 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -341,10 +341,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.has_id = self.data.has_id self.count = self.data.count - # Count times get_metadata is called, and how many times in the cache - self.gm_count = 0 - self.gm_missed = 0 - for prop in ('author_sort', 'authors', 'comment', 'comments', 'isbn', 'publisher', 'rating', 'series', 'series_index', 'tags', 'title', 'timestamp', 'uuid', 'pubdate', 'ondevice'): From bf183471eaec193d6ff345199f4f2188c82116cd Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 12 Jan 2011 11:11:35 +0000 Subject: [PATCH 2/5] Fix problem in search -- the canidates parameter was not passed to get_dates_matches or get_numeric_matches, resulting in an exception. --- src/calibre/library/caches.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py index 6aef45dbbd..4168360d3a 100644 --- a/src/calibre/library/caches.py +++ b/src/calibre/library/caches.py @@ -411,7 +411,8 @@ class ResultCache(SearchQueryParser): # {{{ if isinstance(location, list): if allow_recursion: for loc in location: - matches |= self.get_matches(loc, query, allow_recursion=False) + matches |= self.get_matches(loc, query, candidates, + allow_recursion=False) return matches raise ParseException(query, len(query), 'Recursive query group detected', self) @@ -419,11 +420,11 @@ class ResultCache(SearchQueryParser): # {{{ fm = self.field_metadata[location] # take care of dates special case if fm['datatype'] == 'datetime': - return self.get_dates_matches(location, query.lower()) + return self.get_dates_matches(location, query.lower(), candidates) # take care of numbers special case if fm['datatype'] in ('rating', 'int', 'float'): - return self.get_numeric_matches(location, query.lower()) + return self.get_numeric_matches(location, query.lower(), candidates) # take care of the 'count' operator for is_multiples if fm['is_multiple'] and \ @@ -431,7 +432,8 @@ class ResultCache(SearchQueryParser): # {{{ query[1:1] in '=<>!': vf = lambda item, loc=fm['rec_index'], ms=fm['is_multiple']:\ len(item[loc].split(ms)) if item[loc] is not None else 0 - return self.get_numeric_matches(location, query[1:], val_func=vf) + return self.get_numeric_matches(location, query[1:], + candidates, val_func=vf) # everything else, or 'all' matches matchkind = CONTAINS_MATCH From b09b3fc993c7c7566e88861926ae9f22a893cd66 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 12 Jan 2011 11:13:14 +0000 Subject: [PATCH 3/5] Fix problem with plugin registration. If a plugin disappears without being correctly removed, then building the current action set threw an exception. The only way around it was to hack the preferences. The fix simply ignores missing actions. --- src/calibre/gui2/preferences/toolbar.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/preferences/toolbar.py b/src/calibre/gui2/preferences/toolbar.py index c13d956aea..26cdea19d3 100644 --- a/src/calibre/gui2/preferences/toolbar.py +++ b/src/calibre/gui2/preferences/toolbar.py @@ -37,7 +37,10 @@ class BaseModel(QAbstractListModel): dont_remove_from=set(['toolbar-device'])) if name is None: return FakeAction('--- '+_('Separator')+' ---', None) - return gui.iactions[name] + try: + return gui.iactions[name] + except: + return None def rowCount(self, parent): return len(self._data) @@ -124,7 +127,8 @@ class CurrentModel(BaseModel): BaseModel.__init__(self) self.gprefs_name = 'action-layout-'+key current = gprefs[self.gprefs_name] - self._data = [self.name_to_action(x, gui) for x in current] + self._data = [self.name_to_action(x, gui) for x in current] + self._data = [x for x in self._data if x is not None] self.key = key self.gui = gui From 34424068389e66c82156dca78b54175c114859cb Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 12 Jan 2011 15:32:00 +0000 Subject: [PATCH 4/5] Add ability to highlight when searching instead of restrict --- src/calibre/gui2/layout.py | 14 ++++++++++---- src/calibre/gui2/library/models.py | 22 ++++++++++++++++++++-- src/calibre/gui2/search_box.py | 4 ++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index aaaf1b0267..4009f99201 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -8,9 +8,9 @@ __docformat__ = 'restructuredtext en' from functools import partial from PyQt4.Qt import QIcon, Qt, QWidget, QToolBar, QSize, \ - pyqtSignal, QToolButton, QPushButton, \ - QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup, \ - QMenu + pyqtSignal, QToolButton, QMenu, QCheckBox, \ + QObject, QVBoxLayout, QSizePolicy, QLabel, QHBoxLayout, QActionGroup + from calibre.constants import __appname__ from calibre.gui2.search_box import SearchBox2, SavedSearchBox @@ -178,7 +178,9 @@ class SearchBar(QWidget): # {{{ x.setToolTip(_("
Search the list of books by title, author, publisher, tags, comments, etc.
Words separated by spaces are ANDed"))
l.addWidget(x)
- self.search_button = QPushButton(_('&Go!'))
+ self.search_button = QToolButton()
+ self.search_button.setToolButtonStyle(Qt.ToolButtonTextOnly)
+ self.search_button.setText(_('&Go!'))
l.addWidget(self.search_button)
self.search_button.setSizePolicy(QSizePolicy.Minimum,
QSizePolicy.Minimum)
@@ -192,6 +194,10 @@ class SearchBar(QWidget): # {{{
l.addWidget(x)
x.setToolTip(_("Reset Quick Search"))
+ x = parent.search_highlight_only = QCheckBox()
+ x.setText(_('Highlight'))
+ l.addWidget(x)
+
x = parent.saved_search = SavedSearchBox(self)
x.setMaximumSize(QSize(150, 16777215))
x.setMinimumContentsLength(15)
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 49cb1ce182..98e61acf33 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -10,7 +10,7 @@ from contextlib import closing
from operator import attrgetter
from PyQt4.Qt import QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage, \
- QModelIndex, QVariant, QDate
+ QModelIndex, QVariant, QDate, QColor
from calibre.gui2 import NONE, config, UNDEFINED_QDATE
from calibre.utils.pyparsing import ParseException
@@ -93,6 +93,8 @@ class BooksModel(QAbstractTableModel): # {{{
self.bool_no_icon = QIcon(I('list_remove.png'))
self.bool_blank_icon = QIcon(I('blank.png'))
self.device_connected = False
+ self.rows_matching = set()
+ self.highlight_only = False
self.read_config()
def change_alignment(self, colname, alignment):
@@ -229,9 +231,22 @@ class BooksModel(QAbstractTableModel): # {{{
self.endInsertRows()
self.count_changed()
+ def set_highlight_only(self, toWhat):
+ self.highlight_only = toWhat
+ self.research()
+
def search(self, text, reset=True):
try:
- self.db.search(text)
+ if self.highlight_only:
+ self.db.search('')
+ if not text:
+ self.rows_matching = set()
+ else:
+ self.rows_matching = set(self.db.search(text,
+ return_matches=True))
+ else:
+ self.rows_matching = set()
+ self.db.search(text)
except ParseException as e:
self.searched.emit(e.msg)
return
@@ -651,6 +666,9 @@ class BooksModel(QAbstractTableModel): # {{{
return NONE
if role in (Qt.DisplayRole, Qt.EditRole):
return self.column_to_dc_map[col](index.row())
+ elif role == Qt.BackgroundColorRole:
+ if self.id(index) in self.rows_matching:
+ return QColor('lightgreen')
elif role == Qt.DecorationRole:
if self.column_to_dc_decorator_map[col] is not None:
return self.column_to_dc_decorator_map[index.column()](index.row())
diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py
index 9f74abfc86..75d3c14ef1 100644
--- a/src/calibre/gui2/search_box.py
+++ b/src/calibre/gui2/search_box.py
@@ -375,6 +375,7 @@ class SearchBoxMixin(object): # {{{
unicode(self.search.toolTip())))
self.advanced_search_button.setStatusTip(self.advanced_search_button.toolTip())
self.clear_button.setStatusTip(self.clear_button.toolTip())
+ self.search_highlight_only.stateChanged.connect(self.highlight_only_changed)
def focus_search_box(self, *args):
self.search.setFocus(Qt.OtherFocusReason)
@@ -401,6 +402,9 @@ class SearchBoxMixin(object): # {{{
def focus_to_library(self):
self.current_view().setFocus(Qt.OtherFocusReason)
+ def highlight_only_changed(self, toWhat):
+ self.current_view().model().set_highlight_only(toWhat)
+
# }}}
class SavedSearchBoxMixin(object): # {{{
From d21021ed8f2b4e872faf19263727e531570e4923 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Wed, 12 Jan 2011 15:54:09 +0000
Subject: [PATCH 5/5] Clean up focus issues
---
src/calibre/gui2/library/views.py | 6 +++++-
src/calibre/gui2/search_box.py | 1 +
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py
index e1e9cf4456..357b48d1de 100644
--- a/src/calibre/gui2/library/views.py
+++ b/src/calibre/gui2/library/views.py
@@ -680,8 +680,12 @@ class BooksView(QTableView): # {{{
def set_editable(self, editable, supports_backloading):
self._model.set_editable(editable)
+ def search_proxy(self, txt):
+ self._model.search(txt)
+ self.setFocus(Qt.OtherFocusReason)
+
def connect_to_search_box(self, sb, search_done):
- sb.search.connect(self._model.search)
+ sb.search.connect(self.search_proxy)
self._search_done = search_done
self._model.searched.connect(self.search_done)
diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py
index 75d3c14ef1..5808a2dc46 100644
--- a/src/calibre/gui2/search_box.py
+++ b/src/calibre/gui2/search_box.py
@@ -404,6 +404,7 @@ class SearchBoxMixin(object): # {{{
def highlight_only_changed(self, toWhat):
self.current_view().model().set_highlight_only(toWhat)
+ self.focus_to_library()
# }}}