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' name = 'Store'
author = 'John Schember' author = 'John Schember'
actual_plugin = 'calibre.gui2.actions.store:StoreAction' 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, plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
ActionConvert, ActionDelete, ActionEditMetadata, ActionView, ActionConvert, ActionDelete, ActionEditMetadata, ActionView,

View File

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

View File

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

View File

@ -18,9 +18,6 @@ from calibre.gui2.store.search.download_thread import SearchThreadPool, \
CacheUpdateThreadPool CacheUpdateThreadPool
from calibre.gui2.store.search.search_ui import Ui_Dialog from calibre.gui2.store.search.search_ui import Ui_Dialog
HANG_TIME = 75000 # milliseconds seconds
TIMEOUT = 75 # seconds
class SearchDialog(QDialog, Ui_Dialog): class SearchDialog(QDialog, Ui_Dialog):
def __init__(self, istores, parent=None, query=''): def __init__(self, istores, parent=None, query=''):
@ -28,13 +25,22 @@ class SearchDialog(QDialog, Ui_Dialog):
self.setupUi(self) self.setupUi(self)
self.config = JSONConfig('store/search') self.config = JSONConfig('store/search')
self.search_edit.initialize('store_search_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. # We keep a cache of store plugins and reference them by name.
self.store_plugins = istores 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. # Check for results and hung threads.
self.checker = QTimer() self.checker = QTimer()
self.progress_checker = QTimer() self.progress_checker = QTimer()
@ -42,7 +48,7 @@ class SearchDialog(QDialog, Ui_Dialog):
# Update store caches silently. # Update store caches silently.
for p in self.store_plugins.values(): 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 # Add check boxes for each store so the user
# can disable searching specific stores on a # 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. # Add plugins that the user has checked to the search pool's work queue.
for n in store_names: for n in store_names:
if getattr(self, 'store_check_' + n).isChecked(): 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.hang_check = 0
self.checker.start(100) self.checker.start(100)
self.pi.startAnimation() 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.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) 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): def get_results(self):
# We only want the search plugins to run # We only want the search plugins to run
# a maximum set amount of time before giving up. # a maximum set amount of time before giving up.
self.hang_check += 1 self.hang_check += 1
if self.hang_check >= HANG_TIME: if self.hang_check >= self.hang_time:
self.search_pool.abort() self.search_pool.abort()
self.checker.stop() self.checker.stop()
else: else: