This commit is contained in:
Kovid Goyal 2011-05-26 09:02:55 -06:00
commit 4f7e74d5fd
3 changed files with 73 additions and 51 deletions

View File

@ -44,7 +44,7 @@ class StoreAction(InterfaceAction):
def search(self, query=''): def search(self, query=''):
self.show_disclaimer() self.show_disclaimer()
from calibre.gui2.store.search.search import SearchDialog from calibre.gui2.store.search.search import SearchDialog
sd = SearchDialog(self.gui.istores, self.gui, query) sd = SearchDialog(self.gui, self.gui, query)
sd.exec_() sd.exec_()
def _get_selected_row(self): def _get_selected_row(self):

View File

@ -103,7 +103,22 @@ class Matches(QAbstractItemModel):
return Qt.Unchecked return Qt.Unchecked
return Qt.Checked return Qt.Checked
elif role == Qt.ToolTipRole: elif role == Qt.ToolTipRole:
if col == 0:
if is_disabled(result):
return QVariant(_('<p>This store is currently diabled and cannot be used in other parts of calibre.</p>'))
else:
return QVariant(_('<p>This store is currently enabled and can be used in other parts of calibre.</p>'))
elif col == 1:
return QVariant('<p>%s</p>' % result.description) return QVariant('<p>%s</p>' % result.description)
elif col == 2:
if result.drm_free_only:
return QVariant(_('<p>This store only distributes ebooks with DRM.</p>'))
else:
return QVariant(_('<p>This store distributes ebooks with DRM. It may have some titles without DRM, but you will need to check on a per title basis.</p>'))
elif col == 3:
return QVariant(_('<p>This store is headquartered in %s. This is a good indication of what market the store caters to. However, this does not necessarily mean that the store is limited to that market only.</p>') % result.headquarters)
elif col == 4:
return QVariant(_('<p>This store distributes ebooks in the following formats: %s</p>') % ', '.join(result.formats))
return NONE return NONE
def setData(self, index, data, role): def setData(self, index, data, role):

View File

@ -10,10 +10,11 @@ import re
from random import shuffle from random import shuffle
from PyQt4.Qt import (Qt, QDialog, QDialogButtonBox, QTimer, QCheckBox, from PyQt4.Qt import (Qt, QDialog, QDialogButtonBox, QTimer, QCheckBox,
QVBoxLayout, QIcon, QWidget) QVBoxLayout, QIcon, QWidget, QTabWidget)
from calibre.gui2 import JSONConfig, info_dialog from calibre.gui2 import JSONConfig, info_dialog
from calibre.gui2.progress_indicator import ProgressIndicator from calibre.gui2.progress_indicator import ProgressIndicator
from calibre.gui2.store.config.chooser.chooser_widget import StoreChooserWidget
from calibre.gui2.store.config.search.search_widget import StoreConfigWidget from calibre.gui2.store.config.search.search_widget import StoreConfigWidget
from calibre.gui2.store.search.adv_search_builder import AdvSearchBuilderDialog from calibre.gui2.store.search.adv_search_builder import AdvSearchBuilderDialog
from calibre.gui2.store.search.download_thread import SearchThreadPool, \ from calibre.gui2.store.search.download_thread import SearchThreadPool, \
@ -22,7 +23,7 @@ from calibre.gui2.store.search.search_ui import Ui_Dialog
class SearchDialog(QDialog, Ui_Dialog): class SearchDialog(QDialog, Ui_Dialog):
def __init__(self, istores, parent=None, query=''): def __init__(self, gui, parent=None, query=''):
QDialog.__init__(self, parent) QDialog.__init__(self, parent)
self.setupUi(self) self.setupUi(self)
@ -34,8 +35,7 @@ class SearchDialog(QDialog, Ui_Dialog):
# the variables it sets up are used later. # the variables it sets up are used later.
self.load_settings() self.load_settings()
# We keep a cache of store plugins and reference them by name. self.gui = gui
self.store_plugins = istores
# Setup our worker threads. # Setup our worker threads.
self.search_pool = SearchThreadPool(self.search_thread_count) self.search_pool = SearchThreadPool(self.search_thread_count)
@ -49,22 +49,11 @@ class SearchDialog(QDialog, Ui_Dialog):
self.hang_check = 0 self.hang_check = 0
# Update store caches silently. # Update store caches silently.
for p in self.store_plugins.values(): for p in self.gui.istores.values():
self.cache_pool.add_task(p, self.timeout) self.cache_pool.add_task(p, self.timeout)
# Add check boxes for each store so the user self.store_checks = {}
# can disable searching specific stores on a self.setup_store_checks()
# per search basis.
stores_check_widget = QWidget()
store_list_layout = QVBoxLayout()
stores_check_widget.setLayout(store_list_layout)
for x in sorted(self.store_plugins.keys(), key=lambda x: x.lower()):
cbox = QCheckBox(x)
cbox.setChecked(False)
store_list_layout.addWidget(cbox)
setattr(self, 'store_check_' + x, cbox)
store_list_layout.addStretch()
self.store_list.setWidget(stores_check_widget)
# Set the search query # Set the search query
self.search_edit.setText(query) self.search_edit.setText(query)
@ -92,6 +81,27 @@ class SearchDialog(QDialog, Ui_Dialog):
self.restore_state() self.restore_state()
def setup_store_checks(self):
# Add check boxes for each store so the user
# can disable searching specific stores on a
# per search basis.
existing = {}
for n in self.store_checks:
existing[n] = self.store_checks[n].isChecked()
self.store_checks = {}
stores_check_widget = QWidget()
store_list_layout = QVBoxLayout()
stores_check_widget.setLayout(store_list_layout)
for x in sorted(self.gui.istores.keys(), key=lambda x: x.lower()):
cbox = QCheckBox(x)
cbox.setChecked(existing.get(x, False))
store_list_layout.addWidget(cbox)
self.store_checks[x] = cbox
store_list_layout.addStretch()
self.store_list.setWidget(stores_check_widget)
def build_adv_search(self): def build_adv_search(self):
adv = AdvSearchBuilderDialog(self) adv = AdvSearchBuilderDialog(self)
if adv.exec_() == QDialog.Accepted: if adv.exec_() == QDialog.Accepted:
@ -126,11 +136,12 @@ class SearchDialog(QDialog, Ui_Dialog):
# futher filtering. # futher filtering.
self.results_view.model().set_query(query) self.results_view.model().set_query(query)
# Plugins are in alphebetic order. Randomize the # Plugins are in random order that does not change.
# order of plugin names. This way plugins closer # Randomize the ord of the plugin names every time
# there is a search. This way plugins closer
# to a don't have an unfair advantage over # to a don't have an unfair advantage over
# plugins further from a. # plugins further from a.
store_names = self.store_plugins.keys() store_names = self.store_checks.keys()
if not store_names: if not store_names:
return return
# Remove all of our internal filtering logic from the query. # Remove all of our internal filtering logic from the query.
@ -138,8 +149,8 @@ class SearchDialog(QDialog, Ui_Dialog):
shuffle(store_names) shuffle(store_names)
# 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 self.store_checks[n].isChecked():
self.search_pool.add_task(query, n, self.store_plugins[n], self.max_results, self.timeout) self.search_pool.add_task(query, n, self.gui.istores[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()
@ -179,8 +190,8 @@ class SearchDialog(QDialog, Ui_Dialog):
self.config['open_external'] = self.open_external.isChecked() self.config['open_external'] = self.open_external.isChecked()
store_check = {} store_check = {}
for n in self.store_plugins: for k, v in self.store_checks.items():
store_check[n] = getattr(self, 'store_check_' + n).isChecked() store_check[k] = v.isChecked()
self.config['store_checked'] = store_check self.config['store_checked'] = store_check
def restore_state(self): def restore_state(self):
@ -206,8 +217,8 @@ class SearchDialog(QDialog, Ui_Dialog):
store_check = self.config.get('store_checked', None) store_check = self.config.get('store_checked', None)
if store_check: if store_check:
for n in store_check: for n in store_check:
if hasattr(self, 'store_check_' + n): if n in self.store_checks:
getattr(self, 'store_check_' + n).setChecked(store_check[n]) self.store_checks[n].setChecked(store_check[n])
self.results_view.model().sort_col = self.config.get('sort_col', 2) self.results_view.model().sort_col = self.config.get('sort_col', 2)
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)
@ -234,20 +245,27 @@ class SearchDialog(QDialog, Ui_Dialog):
self.config['open_external'] = self.open_external.isChecked() self.config['open_external'] = self.open_external.isChecked()
d = QDialog(self) d = QDialog(self)
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box = QDialogButtonBox(QDialogButtonBox.Close)
v = QVBoxLayout(d) v = QVBoxLayout(d)
button_box.accepted.connect(d.accept) button_box.accepted.connect(d.accept)
button_box.rejected.connect(d.reject) button_box.rejected.connect(d.reject)
d.setWindowTitle(_('Customize get books search')) d.setWindowTitle(_('Customize get books search'))
config_widget = StoreConfigWidget(self.config)
v.addWidget(config_widget) tab_widget = QTabWidget(d)
v.addWidget(tab_widget)
v.addWidget(button_box) v.addWidget(button_box)
d.exec_() chooser_config_widget = StoreChooserWidget()
search_config_widget = StoreConfigWidget(self.config)
if d.result() == QDialog.Accepted: tab_widget.addTab(chooser_config_widget, _('Choose stores'))
config_widget.save_settings() tab_widget.addTab(search_config_widget, _('Configure search'))
d.exec_()
search_config_widget.save_settings()
self.config_changed() self.config_changed()
self.gui.load_store_plugins()
self.setup_store_checks()
def config_changed(self): def config_changed(self):
self.load_settings() self.load_settings()
@ -283,7 +301,7 @@ class SearchDialog(QDialog, Ui_Dialog):
def open_store(self, index): def open_store(self, index):
result = self.results_view.model().get_result(index) result = self.results_view.model().get_result(index)
self.store_plugins[result.store_name].open(self, result.detail_item, self.open_external.isChecked()) self.gui.istores[result.store_name].open(self, result.detail_item, self.open_external.isChecked())
def check_progress(self): def check_progress(self):
if not self.search_pool.threads_running() and not self.results_view.model().cover_pool.threads_running() and not self.results_view.model().details_pool.threads_running(): if not self.search_pool.threads_running() and not self.results_view.model().cover_pool.threads_running() and not self.results_view.model().details_pool.threads_running():
@ -292,27 +310,16 @@ class SearchDialog(QDialog, Ui_Dialog):
if not self.pi.isAnimated(): if not self.pi.isAnimated():
self.pi.startAnimation() self.pi.startAnimation()
def get_store_checks(self):
'''
Returns a list of QCheckBox's for each store.
'''
checks = []
for x in self.store_plugins:
check = getattr(self, 'store_check_' + x, None)
if check:
checks.append(check)
return checks
def stores_select_all(self): def stores_select_all(self):
for check in self.get_store_checks(): for check in self.store_checks.values():
check.setChecked(True) check.setChecked(True)
def stores_select_invert(self): def stores_select_invert(self):
for check in self.get_store_checks(): for check in self.store_checks.values():
check.setChecked(not check.isChecked()) check.setChecked(not check.isChecked())
def stores_select_none(self): def stores_select_none(self):
for check in self.get_store_checks(): for check in self.store_checks.values():
check.setChecked(False) check.setChecked(False)
def dialog_closed(self, result): def dialog_closed(self, result):