Store: Add config widget for search accessible via the store plugin preferences.

This commit is contained in:
John Schember 2011-05-21 18:39:54 -04:00
parent f14c1a65fd
commit 4a8f83305f
4 changed files with 58 additions and 17 deletions

View File

@ -854,6 +854,17 @@ class ActionStore(InterfaceActionBase):
name = 'Store'
author = 'John Schember'
actual_plugin = 'calibre.gui2.actions.store:StoreAction'
def customization_help(self, gui=False):
return 'Customize the behavior of the store search.'
def config_widget(self):
from calibre.gui2.store.config.store import config_widget as get_cw
return get_cw()
def save_settings(self, config_widget):
from calibre.gui2.store.config.store import save_settings as save
save(config_widget)
plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
ActionConvert, ActionDelete, ActionEditMetadata, ActionView,

View File

@ -22,7 +22,7 @@ class GenericDownloadThreadPool(object):
at the end of the function.
'''
def __init__(self, thread_type, thread_count):
def __init__(self, thread_type, thread_count=1):
self.thread_type = thread_type
self.thread_count = thread_count
@ -30,6 +30,9 @@ class GenericDownloadThreadPool(object):
self.results = Queue()
self.threads = []
def set_thread_count(self, thread_count):
self.thread_count = thread_count
def add_task(self):
'''
This must be implemented in a sub class and this function
@ -92,8 +95,8 @@ class SearchThreadPool(GenericDownloadThreadPool):
def __init__(self, thread_count):
GenericDownloadThreadPool.__init__(self, SearchThread, thread_count)
def add_task(self, query, store_name, store_plugin, timeout):
self.tasks.put((query, store_name, store_plugin, timeout))
def add_task(self, query, store_name, store_plugin, max_results, timeout):
self.tasks.put((query, store_name, store_plugin, max_results, timeout))
GenericDownloadThreadPool.add_task(self)
@ -112,8 +115,8 @@ class SearchThread(Thread):
def run(self):
while self._run and not self.tasks.empty():
try:
query, store_name, store_plugin, timeout = self.tasks.get()
for res in store_plugin.search(query, timeout=timeout):
query, store_name, store_plugin, max_results, timeout = self.tasks.get()
for res in store_plugin.search(query, max_results=max_results, timeout=timeout):
if not self._run:
return
res.store_name = store_name

View File

@ -33,7 +33,7 @@ class Matches(QAbstractItemModel):
HEADERS = [_('Cover'), _('Title'), _('Price'), _('DRM'), _('Store')]
HTML_COLS = (1, 4)
def __init__(self):
def __init__(self, cover_thread_count=2, detail_thread_count=4):
QAbstractItemModel.__init__(self)
self.DRM_LOCKED_ICON = QPixmap(I('drm-locked.png')).scaledToHeight(64,
@ -51,8 +51,8 @@ class Matches(QAbstractItemModel):
self.matches = []
self.query = ''
self.search_filter = SearchFilter()
self.cover_pool = CoverThreadPool(2)
self.details_pool = DetailsThreadPool(4)
self.cover_pool = CoverThreadPool(cover_thread_count)
self.details_pool = DetailsThreadPool(detail_thread_count)
self.sort_col = 2
self.sort_order = Qt.AscendingOrder

View File

@ -18,9 +18,6 @@ from calibre.gui2.store.search.download_thread import SearchThreadPool, \
CacheUpdateThreadPool
from calibre.gui2.store.search.search_ui import Ui_Dialog
HANG_TIME = 75000 # milliseconds seconds
TIMEOUT = 75 # seconds
class SearchDialog(QDialog, Ui_Dialog):
def __init__(self, istores, parent=None, query=''):
@ -28,13 +25,22 @@ class SearchDialog(QDialog, Ui_Dialog):
self.setupUi(self)
self.config = JSONConfig('store/search')
self.search_edit.initialize('store_search_search')
# Loads variables that store various settings.
# This needs to be called soon in __init__ because
# the variables it sets up are used later.
self.load_settings()
# We keep a cache of store plugins and reference them by name.
self.store_plugins = istores
self.search_pool = SearchThreadPool(4)
self.cache_pool = CacheUpdateThreadPool(2)
# Setup our worker threads.
self.search_pool = SearchThreadPool(self.search_thread_count)
self.cache_pool = CacheUpdateThreadPool(self.cache_thread_count)
self.results_view.model().cover_pool.set_thread_count(self.cover_thread_count)
self.results_view.model().details_pool.set_thread_count(self.details_thread_count)
# Check for results and hung threads.
self.checker = QTimer()
self.progress_checker = QTimer()
@ -42,7 +48,7 @@ class SearchDialog(QDialog, Ui_Dialog):
# Update store caches silently.
for p in self.store_plugins.values():
self.cache_pool.add_task(p, 30)
self.cache_pool.add_task(p, self.timeout)
# Add check boxes for each store so the user
# can disable searching specific stores on a
@ -128,7 +134,7 @@ class SearchDialog(QDialog, Ui_Dialog):
# Add plugins that the user has checked to the search pool's work queue.
for n in store_names:
if getattr(self, 'store_check_' + n).isChecked():
self.search_pool.add_task(query, n, self.store_plugins[n], TIMEOUT)
self.search_pool.add_task(query, n, self.store_plugins[n], self.max_results, self.timeout)
self.hang_check = 0
self.checker.start(100)
self.pi.startAnimation()
@ -202,11 +208,32 @@ class SearchDialog(QDialog, Ui_Dialog):
self.results_view.model().sort_order = self.config.get('sort_order', Qt.AscendingOrder)
self.results_view.header().setSortIndicator(self.results_view.model().sort_col, self.results_view.model().sort_order)
def load_settings(self):
# Seconds
self.timeout = self.config.get('timeout', 75)
# Milliseconds
self.hang_time = self.config.get('hang_time', 75) * 1000
self.max_results = self.config.get('max_results', 10)
# Number of threads to run for each type of operation
self.search_thread_count = self.config.get('search_thread_count', 4)
self.cache_thread_count = self.config.get('cache_thread_count', 2)
self.cover_thread_count = self.config.get('cover_thread_count', 2)
self.details_thread_count = self.config.get('details_thread_count', 4)
def config_finished(self):
self.load_settings()
self.search_pool.set_thread_count(self.search_thread_count)
self.cache_pool.set_thread_count(self.cache_thread_count)
self.results_view.model().cover_pool.set_thread_count(self.cover_thread_count)
self.results_view.model().details_pool.set_thread_count(self.details_thread_count)
def get_results(self):
# We only want the search plugins to run
# a maximum set amount of time before giving up.
self.hang_check += 1
if self.hang_check >= HANG_TIME:
if self.hang_check >= self.hang_time:
self.search_pool.abort()
self.checker.stop()
else: