diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py index 823ef77bc5..6a3f591450 100644 --- a/src/calibre/library/caches.py +++ b/src/calibre/library/caches.py @@ -7,7 +7,7 @@ __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' import re, itertools, time, traceback -from itertools import repeat +from itertools import repeat, izip from datetime import timedelta from threading import Thread @@ -194,6 +194,7 @@ class ResultCache(SearchQueryParser): # {{{ self.first_sort = True self.search_restriction = '' self.search_restriction_book_count = 0 + self.marked_ids_dict = {} self.field_metadata = field_metadata self.all_search_locations = field_metadata.get_search_terms() SearchQueryParser.__init__(self, self.all_search_locations, optimize=True) @@ -775,6 +776,34 @@ class ResultCache(SearchQueryParser): # {{{ def get_search_restriction_book_count(self): return self.search_restriction_book_count + def set_marked_ids(self, id_dict): + ''' + ids in id_dict are "marked". They can be searched for by + using the search term ``marked:true`` + + :param id_dict: Either a dictionary mapping ids to values or a sequence + of ids. In the latter case, the value is set to 'true' for all ids. If + a mapping is provided, then the search can be used to search for + particular values: ``marked:value`` + ''' + if not hasattr(id_dict, 'items'): + # Simple list. Make it a dict of string 'true' + self.marked_ids_dict = dict(izip(id_dict, repeat(u'true', + len(id_dict)))) + else: + self.marked_ids_dict = dict(**id_dict) + # Ensure that all the items in the dict are text + for id_,val in self.marked_ids_dict.iteritems(): + self.marked_ids_dict[id_] = unicode(val) + + # Set the values in the cache + marked_col = self.FIELD_MAP['marked'] + for id_,val in self.marked_ids_dict.iteritems(): + try: + self._data[id_][marked_col] = val + except: + pass + # }}} def remove(self, id): @@ -824,6 +853,7 @@ class ResultCache(SearchQueryParser): # {{{ self._data[id] = CacheRow(db, self.composites, db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]) self._data[id].append(db.book_on_device_string(id)) + self._data[id].append(self.marked_ids_dict.get(id, None)) except IndexError: return None try: @@ -840,6 +870,7 @@ class ResultCache(SearchQueryParser): # {{{ self._data[id] = CacheRow(db, self.composites, db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]) self._data[id].append(db.book_on_device_string(id)) + self._data[id].append(self.marked_ids_dict.get(id, None)) self._map[0:0] = ids self._map_filtered[0:0] = ids @@ -864,6 +895,15 @@ class ResultCache(SearchQueryParser): # {{{ for item in self._data: if item is not None: item.append(db.book_on_device_string(item[0])) + item.append(None) + + marked_col = self.FIELD_MAP['marked'] + for id_,val in self.marked_ids_dict.iteritems(): + try: + self._data[id_][marked_col] = val + except: + pass + self._map = [i[0] for i in self._data if i is not None] if field is not None: self.sort(field, ascending) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 3b712e1c10..b506e7e82d 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -374,6 +374,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.FIELD_MAP['ondevice'] = base = base+1 self.field_metadata.set_field_record_index('ondevice', base, prefer_custom=False) + self.FIELD_MAP['marked'] = base = base+1 + self.field_metadata.set_field_record_index('marked', base, prefer_custom=False) script = ''' DROP VIEW IF EXISTS meta2; @@ -421,6 +423,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.row = self.data.row self.has_id = self.data.has_id self.count = self.data.count + self.set_marked_ids = self.data.set_marked_ids for prop in ( 'author_sort', 'authors', 'comment', 'comments', diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py index ff38af6890..b8180f9f39 100644 --- a/src/calibre/library/field_metadata.py +++ b/src/calibre/library/field_metadata.py @@ -273,6 +273,16 @@ class FieldMetadata(dict): 'is_custom':False, 'is_category':False, 'is_csp': False}), + ('marked', {'table':None, + 'column':None, + 'datatype':'text', + 'is_multiple':None, + 'kind':'field', + 'name': None, + 'search_terms':['marked'], + 'is_custom':False, + 'is_category':False, + 'is_csp': False}), ('series_index',{'table':None, 'column':None, 'datatype':'float',