mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Ensure that QPixmap objects are never deleted on non-GUI threads
This commit is contained in:
parent
0541a118e6
commit
a914e95d9f
@ -10,7 +10,7 @@ import itertools, operator, os
|
|||||||
from types import MethodType
|
from types import MethodType
|
||||||
from time import time
|
from time import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from threading import Lock, Event, Thread
|
from threading import Lock, Event, Thread, current_thread
|
||||||
from Queue import Queue
|
from Queue import Queue
|
||||||
from functools import wraps, partial
|
from functools import wraps, partial
|
||||||
|
|
||||||
@ -276,17 +276,29 @@ class CoverCache(dict):
|
|||||||
self.items = OrderedDict()
|
self.items = OrderedDict()
|
||||||
self.lock = Lock()
|
self.lock = Lock()
|
||||||
self.limit = limit
|
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_id):
|
def invalidate(self, book_id):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.items.pop(book_id, None)
|
self._pop(book_id)
|
||||||
|
|
||||||
|
def _pop(self, book_id):
|
||||||
|
val = self.items.pop(book_id, None)
|
||||||
|
if type(val) is QPixmap and current_thread() is not self.gui_thread:
|
||||||
|
self.pixmap_staging.append(val)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
' Must be called in the GUI thread '
|
' Must be called in the GUI thread '
|
||||||
with self.lock:
|
with self.lock:
|
||||||
|
self.clear_staging()
|
||||||
ans = self.items.pop(key, False) # pop() so that item is moved to the top
|
ans = self.items.pop(key, False) # pop() so that item is moved to the top
|
||||||
if ans is not False:
|
if ans is not False:
|
||||||
if isinstance(ans, QImage):
|
if type(ans) is QImage:
|
||||||
# Convert to QPixmap, since rendering QPixmap is much
|
# Convert to QPixmap, since rendering QPixmap is much
|
||||||
# faster
|
# faster
|
||||||
ans = QPixmap.fromImage(ans)
|
ans = QPixmap.fromImage(ans)
|
||||||
@ -296,13 +308,16 @@ class CoverCache(dict):
|
|||||||
|
|
||||||
def set(self, key, val):
|
def set(self, key, val):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.items.pop(key, None) # pop() so that item is moved to the top
|
self._pop(key) # pop() so that item is moved to the top
|
||||||
self.items[key] = val
|
self.items[key] = val
|
||||||
if len(self.items) > self.limit:
|
if len(self.items) > self.limit:
|
||||||
del self.items[next(self.items.iterkeys())]
|
del self.items[next(self.items.iterkeys())]
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
|
if current_thread() is not self.gui_thread:
|
||||||
|
pixmaps = (x for x in self.items.itervalues() if type(x) is QPixmap)
|
||||||
|
self.pixmap_staging.extend(pixmaps)
|
||||||
self.items.clear()
|
self.items.clear()
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
@ -315,7 +330,7 @@ class CoverCache(dict):
|
|||||||
extra = len(self.items) - self.limit
|
extra = len(self.items) - self.limit
|
||||||
remove = tuple(self.iterkeys())[:extra]
|
remove = tuple(self.iterkeys())[:extra]
|
||||||
for k in remove:
|
for k in remove:
|
||||||
del self.items[k]
|
self._pop(k)
|
||||||
|
|
||||||
class CoverDelegate(QStyledItemDelegate):
|
class CoverDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
@ -471,6 +486,7 @@ class GridView(QListView):
|
|||||||
self.update_item.emit(book_id)
|
self.update_item.emit(book_id)
|
||||||
|
|
||||||
def re_render(self, book_id):
|
def re_render(self, book_id):
|
||||||
|
self.delegate.cover_cache.clear_staging()
|
||||||
m = self.model()
|
m = self.model()
|
||||||
try:
|
try:
|
||||||
index = m.db.row(book_id)
|
index = m.db.row(book_id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user