%PDF- %PDF-
| Direktori : /lib/calibre/calibre/gui2/library/ |
| Current File : //lib/calibre/calibre/gui2/library/caches.py |
#!/usr/bin/env python3
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
from threading import Lock, current_thread
from collections import OrderedDict
from qt.core import QImage, QPixmap
from calibre.db.utils import ThumbnailCache as TC
from polyglot.builtins import itervalues
class ThumbnailCache(TC):
def __init__(self, max_size=1024, thumbnail_size=(100, 100)):
TC.__init__(self, name='gui-thumbnail-cache', min_disk_cache=100, max_size=max_size, thumbnail_size=thumbnail_size)
def set_database(self, db):
TC.set_group_id(self, db.library_id)
class CoverCache(dict):
' This is a RAM cache to speed up rendering of covers by storing them as QPixmaps '
def __init__(self, limit=100):
self.items = OrderedDict()
self.lock = Lock()
self.limit = limit
self.pixmap_staging = []
self.gui_thread = current_thread()
def clear_staging(self):
' Must be called in the GUI thread '
self.pixmap_staging = []
def invalidate(self, book_ids):
with self.lock:
for book_id in book_ids:
self._pop(book_id)
def _pop(self, book_id):
val = self.items.pop(book_id, None)
if isinstance(val, QPixmap) and current_thread() is not self.gui_thread:
self.pixmap_staging.append(val)
def __getitem__(self, key):
' Must be called in the GUI thread '
with self.lock:
self.clear_staging()
ans = self.items.pop(key, False) # pop() so that item is moved to the top
if ans is not False:
if isinstance(ans, QImage):
# Convert to QPixmap, since rendering QPixmap is much
# faster
ans = QPixmap.fromImage(ans)
self.items[key] = ans
return ans
def set(self, key, val):
with self.lock:
self._pop(key) # pop() so that item is moved to the top
self.items[key] = val
if len(self.items) > self.limit:
del self.items[next(iter(self.items))]
def clear(self):
with self.lock:
if current_thread() is not self.gui_thread:
pixmaps = (x for x in itervalues(self.items) if isinstance(x, QPixmap))
self.pixmap_staging.extend(pixmaps)
self.items.clear()
def __hash__(self):
return id(self)
def set_limit(self, limit):
with self.lock:
self.limit = limit
if len(self.items) > self.limit:
extra = len(self.items) - self.limit
remove = tuple(self)[:extra]
for k in remove:
self._pop(k)